Chromium Code Reviews| Index: test/mjsunit/strong/load-property.js |
| diff --git a/test/mjsunit/strong/load-property.js b/test/mjsunit/strong/load-property.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d2a059f99fb998f4f6318e85270a02a85856eaa1 |
| --- /dev/null |
| +++ b/test/mjsunit/strong/load-property.js |
| @@ -0,0 +1,192 @@ |
| +// 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 |
| + |
| +// TODO(conradw): Track implementation of strong bit for other objects, add |
|
rossberg
2015/06/10 08:28:08
See above
conradw
2015/06/10 12:03:23
Done.
|
| +// tests. |
| + |
| +function getObjects() { |
|
rossberg
2015/06/10 08:28:08
See above
conradw
2015/06/10 12:03:23
Done.
|
| + "use strict"; |
| + return [ |
| + {}, |
| + [], |
| + (function(){}), |
| + (class Foo {}) |
| + ]; |
| +} |
| + |
| +function readFromObjectSloppy(o) { |
| + return o.foo; |
| +} |
| + |
| +function readFromObjectKeyedSloppy(o) { |
| + return o["foo"]; |
| +} |
| + |
| +function readFromObjectKeyedVarSloppy(o) { |
| + var a = "foo"; |
| + return o[a]; |
| +} |
| + |
| +function readFromObjectKeyedComputedSloppy(o) { |
| + var a = "o"; |
| + return o["fo" + a]; |
| +} |
| + |
| +function readFromObjectStrong(o) { |
| + "use strong"; |
| + return o.foo; |
| +} |
| + |
| +function readFromObjectKeyedStrong(o) { |
| + "use strong"; |
| + return o["foo"]; |
| +} |
| + |
| +function readFromObjectKeyedLetStrong(o) { |
| + "use strong"; |
| + let a = "foo"; |
| + return o[a]; |
| +} |
| + |
| +function readFromObjectKeyedComputedStrong(o) { |
| + "use strong"; |
| + let a = "o"; |
| + return o["fo" + a]; |
| +} |
| + |
| +function getDescs(x) { |
| + return [ |
| + {value: x}, |
| + {configurable: true, 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 = [ |
| + "foo" |
| + ] |
| + |
| + let badKeys = [ |
| + "bar", |
| + "1", |
| + "100001", |
| + "3000000001", |
| + "5000000001" |
| + ]; |
| + |
| + let values = [ |
| + "string", |
| + 1, |
| + 100001, |
| + 30000000001, |
| + 50000000001, |
| + NaN, |
| + {}, |
| + undefined |
| + ]; |
| + |
| + let badAccessorDescs = [ |
| + { set: (function(){}) }, |
| + { configurable: true, set: (function(){}) }, |
| + { configurable: true, enumerable: true, set: (function(){}) } |
| + ]; |
| + |
| + let readSloppy = [ |
| + readFromObjectSloppy, |
| + readFromObjectKeyedSloppy, |
| + readFromObjectKeyedVarSloppy, |
| + readFromObjectKeyedComputedSloppy |
| + ]; |
| + |
| + let readStrong = [ |
| + readFromObjectStrong, |
| + readFromObjectKeyedStrong, |
| + readFromObjectKeyedLetStrong, |
| + readFromObjectKeyedComputedStrong |
| + ]; |
| + |
| + 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(){}) }) |
| + } |
| + |
| + // Attempting to access a property on an objects with no defined properties |
| + // should throw. |
| + for (let object of getObjects()) { |
| + for (let func of readStrong) { |
| + assertStrongSemantics(func, object); |
| + } |
| + for (let func of readSloppy) { |
| + assertSloppySemantics(func, object); |
| + } |
| + // 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); |
| + } |
| + } |
| +})(); |