blob: f3465028b7c45192bd28cba8ae0b065247b7c2d7 [file] [log] [blame]
// 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);
}
}
}
}
}
}
})();