blob: 293ae70cb333baf9ee64f579cb8d86786c61f2dd [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script>
class ClassA { }
class ClassB extends ClassA { }
class ClassC extends ClassB { }
var Instances = {
ClassA: new ClassA,
ClassB: new ClassB,
ClassC: new ClassC,
Object: new Object,
Function: new Function,
Array: new Array,
Boolean: new Boolean,
String: new String,
Symbol: Symbol(),
Number: new Number,
Date: new Date,
RegExp: new RegExp,
Map: new Map,
Set: new Set,
Promise: new Promise(function() {}),
};
var Proxies = {
constructor: Proxy,
basic: new Proxy({}, {}),
object: new Proxy({}, { get() { return Object.prototype; } }),
tricky: new Proxy({}, { get() { return this.count++ === 0 ? ClassA : Object.prototype; } }),
};
var objectWithDisallowedPrototypeGetter = {
get prototype() { return Object.prototype; },
};
var objectWithErrorPrototypeGetter = {
get prototype() { throw 42; },
};
class FunctionPrototypeReplacement { };
Function.prototype.__proto__ = FunctionPrototypeReplacement.prototype;
class ArrayPrototypeReplacement { };
Array.prototype.__proto__ = ArrayPrototypeReplacement.prototype;
class MapPrototypeReplacement { };
Map.prototype.__proto__ = MapPrototypeReplacement.prototype;
class SetPrototypeReplacement { };
Set.prototype.__proto__ = SetPrototypeReplacement.prototype;
class PromisePrototypeReplacement { };
Promise.prototype.__proto__ = PromisePrototypeReplacement.prototype;
function clearInstances() {
Instances = {};
}
function test() {
function queryInstances(prototypeOrConstructor, callback) {
WI.runtimeManager.evaluateInInspectedWindow(`queryInstances(${prototypeOrConstructor})`, {objectGroup: "test", includeCommandLineAPI: true, generatePreview: true}, callback);
}
let suite = InspectorTest.createAsyncSuite("CommandLineAPI.queryInstances");
let cases = [
{prototypeOrConstructor: `Instances.ClassA`, resultCount: 0},
{prototypeOrConstructor: `ClassA`, resultCount: 5},
{prototypeOrConstructor: `ClassA.prototype`, resultCount: 5},
{prototypeOrConstructor: `Instances.ClassB`, resultCount: 0},
{prototypeOrConstructor: `ClassB`, resultCount: 3},
{prototypeOrConstructor: `ClassB.prototype`, resultCount: 3},
{prototypeOrConstructor: `Instances.ClassC`, resultCount: 0},
{prototypeOrConstructor: `ClassC`, resultCount: 1},
{prototypeOrConstructor: `ClassC.prototype`, resultCount: 1},
{prototypeOrConstructor: `HTMLDocument`, resultCount: 1},
{prototypeOrConstructor: `HTMLBodyElement`, resultCount: 1},
{prototypeOrConstructor: `HTMLImageElement`, resultCount: 0},
{prototypeOrConstructor: `objectWithDisallowedPrototypeGetter`, resultCount: 0},
{prototypeOrConstructor: `objectWithErrorPrototypeGetter`, resultCount: 0},
{prototypeOrConstructor: `undefined`, shouldThrow: true},
{prototypeOrConstructor: `null`, shouldThrow: true},
{prototypeOrConstructor: `Infinity`, shouldThrow: true},
{prototypeOrConstructor: `NaN`, shouldThrow: true},
{prototypeOrConstructor: `1`, shouldThrow: true},
{prototypeOrConstructor: `true`, shouldThrow: true},
{prototypeOrConstructor: `"test"`, shouldThrow: true},
{prototypeOrConstructor: `Instances.Symbol`, shouldThrow: true},
{prototypeOrConstructor: `Symbol`, resultCount: 0},
{prototypeOrConstructor: `Symbol.prototype`, resultCount: 0},
{prototypeOrConstructor: `Proxies.constructor`, resultCount: 0},
{prototypeOrConstructor: `Proxies.basic`, shouldThrow: true},
{prototypeOrConstructor: `Proxies.object`, shouldThrow: true},
{prototypeOrConstructor: `Proxies.tricky`, shouldThrow: true},
];
for (let type of ["Object", "Function", "Array", "Map", "Set", "Promise"]) {
cases.push({prototypeOrConstructor: `Instances.${type}`, resultCount: 0});
cases.push({prototypeOrConstructor: type, shouldThrow: true});
cases.push({prototypeOrConstructor: `${type}.prototype`, shouldThrow: true});
}
for (let type of ["FunctionPrototypeReplacement", "ArrayPrototypeReplacement", "MapPrototypeReplacement", "SetPrototypeReplacement", "PromisePrototypeReplacement"]) {
cases.push({prototypeOrConstructor: type, shouldThrow: true});
cases.push({prototypeOrConstructor: `${type}.prototype`, shouldThrow: true});
}
for (let type of ["Boolean", "String", "Number", "Date", "RegExp"]) {
cases.push({prototypeOrConstructor: `Instances.${type}`, resultCount: 0});
cases.push({prototypeOrConstructor: type});
cases.push({prototypeOrConstructor: `${type}.prototype`});
}
for (let {prototypeOrConstructor, resultCount, shouldThrow} of cases) {
suite.addTestCase({
name: `CommandLineAPI.queryInstances.${prototypeOrConstructor}`,
test(resolve, reject) {
queryInstances(prototypeOrConstructor, (remoteObject, wasThrown, savedResultIndex) => {
if (shouldThrow) {
InspectorTest.expectThat(wasThrown, `Calling "queryInstances" with "${prototypeOrConstructor}" should throw an exception.`);
InspectorTest.log(remoteObject.description);
if (wasThrown) {
resolve();
return;
}
} else if (wasThrown) {
InspectorTest.fail("An exception was thrown.");
InspectorTest.log(remoteObject.description);
resolve();
return;
}
InspectorTest.expectEqual(remoteObject.type, "object", "The result should be an object.");
InspectorTest.expectEqual(remoteObject.subtype, "array", "The result should be an array object.");
if (resultCount === undefined)
InspectorTest.expectGreaterThan(remoteObject.size, 0, `The result should have at least 1 item.`);
else {
InspectorTest.expectEqual(remoteObject.size, resultCount, `The result should have ${resultCount} items.`);
if (remoteObject.size) {
let propertyPreviews = remoteObject.preview.propertyPreviews.map((preview) => preview.value);
propertyPreviews.sort();
InspectorTest.log("[" + propertyPreviews.join(", ") + "]");
}
}
resolve();
});
}
});
}
suite.addTestCase({
name: "CommandLineAPI.queryInstances.GC",
test(resolve, reject) {
queryInstances(`ClassC`, (remoteObject, wasThrown, savedResultIndex) => {
InspectorTest.assert(!wasThrown);
if (wasThrown)
InspectorTest.log(remoteObject.description);
InspectorTest.expectEqual(remoteObject.size, 1, `Should be 1 ClassC instance.`);
InspectorTest.log("Clearing instances...");
RuntimeAgent.releaseObjectGroup("test");
InspectorTest.evaluateInPage(`clearInstances()`);
queryInstances(`ClassC`, (remoteObject, wasThrown, savedResultIndex) => {
InspectorTest.assert(!wasThrown);
if (wasThrown)
InspectorTest.log(remoteObject.description);
InspectorTest.expectEqual(remoteObject.size, 0, `Should now be 0 ClassC instances.`);
resolve();
});
});
}
});
suite.addTestCase({
name: "CommandLineAPI.queryInstances.NoParameter",
test(resolve, reject) {
const prototypeOrConstructor = "";
queryInstances(prototypeOrConstructor, (remoteObject, wasThrown, savedResultIndex) => {
if (wasThrown) {
InspectorTest.fail("An exception was thrown.");
InspectorTest.log(remoteObject.description);
reject();
return;
}
InspectorTest.expectEqual(remoteObject.type, "undefined", "The result should be undefined.");
resolve();
});
}
});
suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Tests for the `queryInstances` function in the Command Line API.</p>
</body>
</html>