Last active
December 4, 2022 05:15
-
-
Save seia-soto/3b6ea1b35631cbe64f9b05b4636e495f to your computer and use it in GitHub Desktop.
Inspector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name New script | |
// @namespace Violentmonkey Scripts | |
// @match *://*/* | |
// @grant unsafeWindow | |
// @version 1.0 | |
// @author - | |
// @description 12/2/2022, 12:42:04 PM | |
// ==/UserScript== | |
"use strict"; | |
(() => { | |
// src/inspector.ts | |
(() => { | |
let thisWindow = window; | |
if (typeof unsafeWindow !== "undefined") { | |
console.log("unsafeWindow found"); | |
thisWindow = unsafeWindow; | |
} | |
const tails = []; | |
const proxyLog = new Proxy( | |
console.log, | |
{ | |
apply(target, thisArg, argArray) { | |
tails.push(argArray.join(" ")); | |
} | |
} | |
); | |
const defaultGetOwnPropertyDescriptor = thisWindow.Object.getOwnPropertyDescriptor; | |
const mocks = [ | |
{ | |
reference: thisWindow.Object, | |
key: "getOwnPropertyDescriptor", | |
use: defaultGetOwnPropertyDescriptor(thisWindow.Object, "getOwnPropertyDescriptor") | |
}, | |
{ | |
reference: Object, | |
key: "getOwnPropertyDescriptors", | |
use: defaultGetOwnPropertyDescriptor(thisWindow.Object, "getOwnPropertyDescriptors") | |
} | |
]; | |
const defineProperty = new Proxy( | |
thisWindow.Object.defineProperty, | |
{ | |
apply(target, thisArg, argArray) { | |
const [obj, key] = argArray; | |
mocks.push({ | |
reference: obj, | |
key | |
}); | |
return Reflect.apply(target, thisArg, argArray); | |
} | |
} | |
); | |
function createNativeCodeLiteral(name) { | |
return `function ${name}() { [native code] }`; | |
} | |
const defaultGetOwnPropertyDescriptors = Object.getOwnPropertyDescriptors; | |
const defaultReflectGetOwnPropertyDescriptor = Reflect.getOwnPropertyDescriptor; | |
Object.defineProperties( | |
Object, | |
{ | |
getOwnPropertyDescriptor: { | |
get() { | |
function getOwnPropertyDescriptor(obj, key) { | |
for (const entry of mocks) { | |
if (entry.reference === obj && entry.key === key) { | |
return entry.use; | |
} | |
} | |
return defaultGetOwnPropertyDescriptor(obj, key); | |
} | |
getOwnPropertyDescriptor.toString = function toString() { | |
return createNativeCodeLiteral("getOwnPropertyDescriptor"); | |
}; | |
return getOwnPropertyDescriptor; | |
} | |
}, | |
getOwnPropertyDescriptors: { | |
get() { | |
function getOwnPropertyDescriptors(obj) { | |
const result = defaultGetOwnPropertyDescriptors(obj); | |
for (const entry of mocks) { | |
if (entry.reference === obj) { | |
if (typeof entry.use === "undefined") { | |
delete result[entry.key]; | |
continue; | |
} | |
result[entry.key] = entry.use; | |
} | |
} | |
return result; | |
} | |
getOwnPropertyDescriptors.toString = function toString() { | |
return createNativeCodeLiteral("getOwnPropertyDescriptors"); | |
}; | |
return getOwnPropertyDescriptors; | |
} | |
} | |
} | |
); | |
Object.defineProperties( | |
Reflect, | |
{ | |
getOwnPropertyDescriptor: { | |
get() { | |
function getOwnPropertyDescriptor(obj, key) { | |
for (const entry of mocks) { | |
if (entry.reference === obj && entry.key === key) { | |
return entry.use; | |
} | |
} | |
return defaultReflectGetOwnPropertyDescriptor(obj, key); | |
} | |
getOwnPropertyDescriptor.toString = function toString() { | |
return createNativeCodeLiteral("getOwnPropertyDescriptor"); | |
}; | |
return getOwnPropertyDescriptor; | |
} | |
} | |
} | |
); | |
defineProperty( | |
thisWindow, | |
"__seia_get_tails__", | |
{ | |
get() { | |
return console.log(JSON.stringify(tails)); | |
}, | |
enumerable: false | |
} | |
); | |
const inspected = []; | |
const whitelisted = [ | |
{ | |
reference: Object, | |
key: "defineProperty" | |
}, | |
{ | |
reference: Object, | |
key: "defineProperties" | |
} | |
]; | |
function inspect(obj = thisWindow, prefix = "window") { | |
for (const old of inspected) { | |
if (obj === old) { | |
return; | |
} | |
} | |
inspected.push(obj); | |
for (const key in obj) { | |
const original = obj[key]; | |
try { | |
if (typeof whitelisted.find((whitelist) => whitelist.reference === obj && whitelist.key === key) !== "undefined") { | |
continue; | |
} | |
defineProperty( | |
obj, | |
key, | |
{ | |
get() { | |
proxyLog("get", prefix + "." + key, original); | |
if (typeof original === "object") { | |
inspect(original, prefix + "." + key); | |
} else if (typeof original === "function") { | |
return new Proxy( | |
original, | |
{ | |
apply(target, thisArg, argArray) { | |
proxyLog("apply", prefix + "." + key, original, argArray); | |
return Reflect.apply(target, thisArg, argArray); | |
} | |
} | |
); | |
} | |
return original; | |
} | |
} | |
); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
} | |
inspect(thisWindow); | |
inspect(thisWindow.Object, "Object"); | |
inspect(thisWindow.Array, "Array"); | |
inspect(thisWindow.JSON, "JSON"); | |
})(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment