@fast-check/poisoning
Version:
Set of utilities to ease detection and revert of poisoning
77 lines (76 loc) • 3.78 kB
JavaScript
import { PoisoningFreeArray, PushSymbol } from './PoisoningFreeArray.js';
import { EntriesSymbol, HasSymbol } from './PoisoningFreeMap.js';
const SString = String;
const safeObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
const safeObjectGetOwnPropertyNames = Object.getOwnPropertyNames;
const safeObjectGetOwnPropertySymbols = Object.getOwnPropertySymbols;
const safeObjectIs = Object.is;
const safeObjectDefineProperty = Object.defineProperty;
export function trackDiffsOnGlobals(initialGlobals, isEligibleGlobal, isEligibleProperty) {
const allInitialGlobals = [...initialGlobals[EntriesSymbol]()];
const observedDiffs = PoisoningFreeArray.from([]);
for (let index = 0; index !== allInitialGlobals.length; ++index) {
const instance = allInitialGlobals[index][0];
const globalDetails = allInitialGlobals[index][1];
if (!isEligibleGlobal(globalDetails)) {
continue;
}
const name = globalDetails.name;
const initialProperties = globalDetails.properties;
const initialPropertiesList = [...initialProperties[EntriesSymbol]()];
for (let propertyIndex = 0; propertyIndex !== initialPropertiesList.length; ++propertyIndex) {
const propertyName = initialPropertiesList[propertyIndex][0];
const initialPropertyDescriptor = initialPropertiesList[propertyIndex][1];
if (!isEligibleProperty(globalDetails, SString(propertyName))) {
continue;
}
const currentDescriptor = safeObjectGetOwnPropertyDescriptor(instance, propertyName);
if (currentDescriptor === undefined) {
observedDiffs[PushSymbol]({
keyName: SString(propertyName),
fullyQualifiedKeyName: name + '.' + SString(propertyName),
type: 'removed',
patch: () => {
safeObjectDefineProperty(instance, propertyName, initialPropertyDescriptor);
},
globalDetails,
});
}
else if (!safeObjectIs(initialPropertyDescriptor.value, currentDescriptor.value) ||
!safeObjectIs(initialPropertyDescriptor.get, currentDescriptor.get) ||
!safeObjectIs(initialPropertyDescriptor.set, currentDescriptor.set)) {
observedDiffs[PushSymbol]({
keyName: SString(propertyName),
fullyQualifiedKeyName: name + '.' + SString(propertyName),
type: 'changed',
patch: () => {
safeObjectDefineProperty(instance, propertyName, initialPropertyDescriptor);
},
globalDetails,
});
}
}
const currentDescriptorsList = [
...safeObjectGetOwnPropertyNames(instance),
...safeObjectGetOwnPropertySymbols(instance),
];
for (let descriptorIndex = 0; descriptorIndex !== currentDescriptorsList.length; ++descriptorIndex) {
const propertyName = currentDescriptorsList[descriptorIndex];
if (!isEligibleProperty(globalDetails, SString(propertyName))) {
continue;
}
if (!initialProperties[HasSymbol](propertyName)) {
observedDiffs[PushSymbol]({
keyName: SString(propertyName),
fullyQualifiedKeyName: name + '.' + SString(propertyName),
type: 'added',
patch: () => {
delete instance[propertyName];
},
globalDetails,
});
}
}
}
return [...observedDiffs];
}