mirror of
https://github.com/servo/servo.git
synced 2025-06-29 11:33:39 +01:00
107 lines
4 KiB
JavaScript
107 lines
4 KiB
JavaScript
export function isConstructor(o) {
|
|
assert_equals(typeof o, "function", "Must be a function according to typeof");
|
|
assert_true(isConstructorTest(o), "Must be a constructor according to the meta-object protocol");
|
|
assert_throws(new TypeError(), () => o(), "Attempting to call (not construct) must throw");
|
|
}
|
|
|
|
export function functionLength(o, expected, label) {
|
|
const lengthExpected = { writable: false, enumerable: false, configurable: true };
|
|
const { value } = propertyDescriptor(o, "length", lengthExpected);
|
|
|
|
assert_equals(value, expected, `${formatLabel(label)}length value`);
|
|
}
|
|
|
|
export function functionName(o, expected, label) {
|
|
const lengthExpected = { writable: false, enumerable: false, configurable: true };
|
|
const { value } = propertyDescriptor(o, "name", lengthExpected);
|
|
|
|
assert_equals(value, expected, `${formatLabel(label)}name value`);
|
|
}
|
|
|
|
export function hasClassPrototype(o) {
|
|
const prototypeExpected = { writable: false, enumerable: false, configurable: false };
|
|
const { value } = propertyDescriptor(o, "prototype", prototypeExpected);
|
|
assert_equals(typeof value, "object", "prototype must be an object");
|
|
assert_not_equals(value, null, "prototype must not be null");
|
|
}
|
|
|
|
export function hasPrototypeConstructorLink(klass) {
|
|
const constructorExpected = { writable: true, enumerable: false, configurable: true };
|
|
const { value } = propertyDescriptor(klass.prototype, "constructor", constructorExpected);
|
|
assert_equals(value, klass, "constructor property must match");
|
|
}
|
|
|
|
export function propertyKeys(o, expectedNames, expectedSymbols, label) {
|
|
label = formatLabel(label);
|
|
assert_array_equals(Object.getOwnPropertyNames(o), expectedNames, `${label}property names`);
|
|
assert_array_equals(Object.getOwnPropertySymbols(o), expectedSymbols,
|
|
`${label}property symbols`);
|
|
}
|
|
|
|
export function methods(o, expectedMethods) {
|
|
for (const [name, length] of Object.entries(expectedMethods)) {
|
|
method(o, name, length);
|
|
}
|
|
}
|
|
|
|
export function accessors(o, expectedAccessors) {
|
|
for (const [name, accessorTypes] of Object.entries(expectedAccessors)) {
|
|
accessor(o, name, accessorTypes);
|
|
}
|
|
}
|
|
|
|
function method(o, prop, length) {
|
|
const methodExpected = { writable: true, enumerable: false, configurable: true };
|
|
const { value } = propertyDescriptor(o, prop, methodExpected);
|
|
|
|
assert_equals(typeof value, "function", `${prop} method must be a function according to typeof`);
|
|
assert_false(isConstructorTest(value),
|
|
`${prop} method must not be a constructor according to the meta-object protocol`);
|
|
functionLength(value, length, prop);
|
|
functionName(value, prop, prop);
|
|
propertyKeys(value, ["length", "name"], [], prop);
|
|
}
|
|
|
|
function accessor(o, prop, expectedAccessorTypes) {
|
|
const accessorExpected = { enumerable: false, configurable: true };
|
|
const propDesc = propertyDescriptor(o, prop, accessorExpected);
|
|
|
|
for (const possibleType of ["get", "set"]) {
|
|
const accessorFunc = propDesc[possibleType];
|
|
if (expectedAccessorTypes.includes(possibleType)) {
|
|
const label = `${prop}'s ${possibleType}ter`;
|
|
|
|
assert_equals(typeof accessorFunc, "function",
|
|
`${label} must be a function according to typeof`);
|
|
assert_false(isConstructorTest(accessorFunc),
|
|
`${label} must not be a constructor according to the meta-object protocol`);
|
|
|
|
functionLength(accessorFunc, possibleType === "get" ? 0 : 1, label);
|
|
functionName(accessorFunc, `${possibleType} ${prop}`, label);
|
|
propertyKeys(accessorFunc, ["length", "name"], [], label);
|
|
} else {
|
|
assert_equals(accessorFunc, undefined, `${prop} must not have a ${possibleType}ter`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function propertyDescriptor(obj, prop, mustMatch) {
|
|
const propDesc = Object.getOwnPropertyDescriptor(obj, prop);
|
|
for (const key in Object.keys(mustMatch)) {
|
|
assert_equals(propDesc[key], mustMatch[key], `${prop} ${key}`);
|
|
}
|
|
return propDesc;
|
|
}
|
|
|
|
function isConstructorTest(o) {
|
|
try {
|
|
new (new Proxy(o, {construct: () => ({})}));
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function formatLabel(label) {
|
|
return label !== undefined ? ` ${label}` : "";
|
|
}
|