blob: a4ba1e44dac8a9a331de03b0535e392493e65c11 [file] [log] [blame]
function assert(condition) {
if (!condition)
throw new Error("assertion failed");
}
function assert_eq(a, b) {
if (a !== b)
throw new Error("assertion failed: " + a + " === " + b);
}
function assert_neq(a, b) {
if (a === b)
throw new Error("assertion failed: " + a + " !== " + b);
}
noInline(assert)
noInline(assert_eq)
noInline(assert_neq)
function sd(obj) {
let data = $vm.getStructureTransitionList(obj)
let result = []
if (!data)
return result
for (let i = 0; i < data.length/5; ++i) {
result.push({ id: data[i*5+0], offset: data[i*5+1], max: data[i*5+2], property: data[i*5+3], type: data[i*5+4] == 0 ? "added" : "deleted" })
}
return result
}
function sid(obj) {
let data = sd(obj)
return data[data.length-1].id
}
noInline(sd)
noInline(sid)
function testDeleteIsNotUncacheable(i) {
let foo = {}
foo["bar" + i] = 1
foo["baz" + i] = 2
assert(foo["bar" + i] === 1)
assert(foo["baz" + i] === 2)
let oldSid = sid(foo)
assert_eq($vm.getConcurrently(foo, "baz"+i), 1)
assert_eq($vm.getConcurrently(foo, "bar"+i), 1)
assert_eq($vm.getConcurrently(foo, "foo"+i), 0)
assert(delete foo["bar" + i])
assert_neq(oldSid, sid(foo))
assert(!(("bar" + i) in foo));
assert(foo["baz" + i] === 2)
assert_eq($vm.getConcurrently(foo, "baz"+i), 1)
assert_eq($vm.getConcurrently(foo, "bar"+i), 0)
assert_eq(Object.keys(foo).length, 1)
let data = sd(foo)
assert_eq(data[data.length-1].property, "bar" + i)
foo["bar" + i] = 1
assert_eq($vm.getConcurrently(foo, "baz"+i), 1)
assert_eq($vm.getConcurrently(foo, "bar"+i), 1)
assert(foo["bar" + i] === 1)
}
noInline(testDeleteIsNotUncacheable)
function testCanMaterializeDeletes(i) {
let foo = {}
foo["bar" + i] = 1
foo["baz" + i] = 2
assert(foo["bar" + i] === 1)
assert(foo["baz" + i] === 2)
assert(delete foo["bar" + i])
assert(!("bar" + i in foo))
assert(foo["baz" + i] === 2)
assert_eq(Object.keys(foo).length, 1)
let foo2 = {}
foo2["bar" + i] = 3
foo2["baz" + i] = 4
assert(delete foo2["bar" + i])
assert_eq(sid(foo2), sid(foo))
foo2["fun" + i] = 3
assert_neq(sid(foo2), sid(foo))
assert(foo2["fun" + i] === 3)
assert(foo2["baz" + i] === 4)
assert(!("bar" + i in foo2))
assert_eq(Object.keys(foo2).length, 2)
assert(foo["baz" + i] === 2)
assert(!("bar" + i in foo))
assert_eq(Object.keys(foo).length, 1)
let data = sd(foo)
assert_eq(data[data.length-1].property, "bar" + i)
data = sd(foo2)
assert_eq(data[data.length-1].property, "fun" + i)
assert_eq(data[data.length-2].property, "bar" + i)
}
noInline(testCanMaterializeDeletes)
function testCanFlatten(i) {
let foo = {}
for (let j=0; j<500; ++j) {
const oldId = sid(foo)
foo["x" + 1000*j + i] = j
if (j > 0)
delete foo["x" + 1000*(j - 1) + i]
if (j > 100)
assert_eq(sid(foo), oldId)
}
for (let j=0; j<500; ++j) {
const val = foo["x" + 1000*j + i]
if (j == 499)
assert_eq(val, j)
else
assert_eq(val, undefined)
}
$vm.flattenDictionaryObject(foo)
for (let j=0; j<500; ++j) {
const val = foo["x" + 1000*j + i]
if (j == 499)
assert_eq(val, j)
else
assert_eq(val, undefined)
}
}
noInline(testCanFlatten)
function testDeleteWithInlineCache() {
Object.prototype.globalProperty = 42
function makeFoo() {
let foo = {}
foo.baz = 1
assert(foo.globalProperty === 42)
return foo
}
noInline(makeFoo)
function doTest(xVal) {
for (let j=0; j<50; ++j) {
for (let z=0; z<10000; ++z) {
const foo = arr[j]
assert(foo.baz === 1)
assert_eq(Object.keys(foo).length, 1)
assert_eq(foo.globalProperty, xVal)
}
}
}
noInline(doTest)
arr = new Array(50)
for (let j=0; j<50; ++j) {
arr[j] = makeFoo()
if (j > 0)
assert_eq(sid(arr[j-1]), sid(arr[j]))
}
doTest(42)
Object.prototype.globalProperty = 43
doTest(43)
delete Object.prototype.globalProperty
doTest(undefined)
}
noInline(testDeleteWithInlineCache)
testDeleteWithInlineCache()
for (let i = 0; i < 1000; ++i) {
testDeleteIsNotUncacheable(i)
testCanMaterializeDeletes(1000+i)
}
for (let i = 0; i < 100; ++i) {
testCanFlatten(2000+i)
}