UNPKG

@fast-check/poisoning

Version:

Set of utilities to ease detection and revert of poisoning

77 lines (76 loc) 3.78 kB
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]; }