UNPKG

@fast-check/poisoning

Version:

Set of utilities to ease detection and revert of poisoning

88 lines (87 loc) 4.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.captureAllGlobals = captureAllGlobals; const PoisoningFreeArray_js_1 = require("./PoisoningFreeArray.js"); const PoisoningFreeMap_js_1 = require("./PoisoningFreeMap.js"); const PoisoningFreeSet_js_1 = require("./PoisoningFreeSet.js"); const SString = String; const safeObjectGetOwnPropertyDescriptors = Object.getOwnPropertyDescriptors; const safeObjectGetOwnPropertyNames = Object.getOwnPropertyNames; const safeObjectGetOwnPropertySymbols = Object.getOwnPropertySymbols; function compareKeys(keyA, keyB) { const sA = SString(keyA[0]); const sB = SString(keyB[0]); return sA < sB ? -1 : sA > sB ? 1 : 0; } function extractAllDescriptorsDetails(instance) { const descriptors = safeObjectGetOwnPropertyDescriptors(instance); const allDescriptors = PoisoningFreeArray_js_1.PoisoningFreeArray.from([ ...safeObjectGetOwnPropertyNames(descriptors), ...safeObjectGetOwnPropertySymbols(descriptors), ]); const allDescriptorsDetails = PoisoningFreeArray_js_1.PoisoningFreeArray.from(allDescriptors[PoisoningFreeArray_js_1.MapSymbol]((name) => [ name, descriptors[name], ])); return allDescriptorsDetails[PoisoningFreeArray_js_1.SortSymbol](compareKeys); } function flagRootRecursively(knownGlobals, instance, currentRoot) { const storedGlobal = knownGlobals[PoisoningFreeMap_js_1.GetSymbol](instance); if (storedGlobal === undefined) { return; } if (storedGlobal.rootAncestors[PoisoningFreeSet_js_1.HasSymbol](currentRoot)) { return; } storedGlobal.rootAncestors[PoisoningFreeSet_js_1.AddSymbol](currentRoot); if (storedGlobal.depth <= 1) { return; } for (const [, descriptor] of storedGlobal.properties) { flagRootRecursively(knownGlobals, descriptor.value, currentRoot); } } function captureAllGlobals() { const knownGlobals = PoisoningFreeMap_js_1.PoisoningFreeMap.from(); const nextCaptures = PoisoningFreeArray_js_1.PoisoningFreeArray.from([ { instance: globalThis, name: 'globalThis', currentDepth: 0, lastRootInPath: 'globalThis' }, ]); while (nextCaptures.length !== 0) { const { instance, name, currentDepth, lastRootInPath } = nextCaptures[PoisoningFreeArray_js_1.ShiftSymbol](); if (typeof instance !== 'function' && typeof instance !== 'object') { continue; } if (instance === null || instance === undefined) { continue; } if (knownGlobals[PoisoningFreeMap_js_1.HasSymbol](instance)) { flagRootRecursively(knownGlobals, instance, lastRootInPath); continue; } const allDescriptorsDetails = extractAllDescriptorsDetails(instance); const localGlobal = { name, depth: currentDepth, properties: PoisoningFreeMap_js_1.PoisoningFreeMap.from(), rootAncestors: PoisoningFreeSet_js_1.PoisoningFreeSet.from([lastRootInPath]), }; knownGlobals[PoisoningFreeMap_js_1.SetSymbol](instance, localGlobal); for (let index = 0; index !== allDescriptorsDetails.length; ++index) { const descriptorName = allDescriptorsDetails[index][0]; const descriptor = allDescriptorsDetails[index][1]; localGlobal.properties[PoisoningFreeMap_js_1.SetSymbol](descriptorName, descriptor); if (typeof descriptorName === 'symbol') { continue; } const subGlobalName = currentDepth !== 0 ? name + '.' + SString(descriptorName) : SString(descriptorName); const newLastRootInPath = currentDepth <= 1 ? name : lastRootInPath; nextCaptures[PoisoningFreeArray_js_1.PushSymbol]({ instance: descriptor.value, name: subGlobalName, currentDepth: currentDepth + 1, lastRootInPath: newLastRootInPath, }); } } return knownGlobals; }