// 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(""), [], // TODO(conradw): uncomment and correct test once Object.defineProperty is // fixed. // 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 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 }); } // After altering the backing store, accessing a missing property should still // throw. for (let key of badKeys) { for (let value of values) { for (let desc of getDescs(value)) { let objects = getObjects(); let nonInheritingObjects = getNonInheritingObjects(); for (let object of objects.concat(nonInheritingObjects)) { Object.defineProperty(object, key, desc); for (let func of readStrong) { assertStrongSemantics(func, object); } for (let func of readSloppy) { assertSloppySemantics(func, object); } } for (let object of objects) { // 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); } } } } } } })();