Last active
October 10, 2022 15:37
-
-
Save j1elo/0acaf233de9f4b2d8bd7f27b9f9a3fb3 to your computer and use it in GitHub Desktop.
Prints the path to all values whose names match the given regular expression.
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
/** | |
* Prints the path to all values whose names match the given regular expression. | |
* | |
* @param {Object} input - An object that contains the parent from where to | |
* start searching recursively for all key names. | |
* | |
* The input object can be passed with just an standalone value, which then | |
* will be used itself as the prefix for the result. | |
* | |
* For example, for a parent object `root` which contains a hierarchy of | |
* other objects, `findValues({ root }, /stream/i)` outputs this: | |
* | |
* root.some.other.array[0].myStream | |
* | |
* To customize the prefix, pass the input with an explicit key name. | |
* | |
* For example, `findValues({ myPrefix: root }, /stream/i)` outputs this: | |
* | |
* myPrefix.some.other.array[0].myStream | |
* | |
* @param {RegExp} nameRegex - A JavaScript [Regular Expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) | |
* which matches the value names that you want to find. | |
* | |
* @returns {void} Nothing. Results of this function go to `console.log()`. | |
*/ | |
function findValues(input, nameRegex) { | |
// Used to avoid circular references. | |
const seen = new WeakSet(); | |
function _findValues(input, nameRegex) { | |
const parentPath = Object.keys(input)[0]; | |
const parentObj = Object.values(input)[0]; | |
if (seen.has(parentObj)) { | |
return; | |
} else { | |
seen.add(parentObj); | |
} | |
for (let [key, value] of Object.entries(parentObj)) { | |
let newPath; | |
if (Array.isArray(parentObj)) { | |
newPath = parentPath + `[${key}]`; | |
} else if (/^[a-zA-Z_$][a-zA-Z\d_$]*$/.test(key)) { | |
// Simple identifier: Can be accessed directly with Dot notation. | |
// FIXME: This test is very simplistic and could be improved. Valid | |
// JavaScript identifiers can be much, _much_ more complex! | |
// See: [What characters are valid for JavaScript variable names?](https://stackoverflow.com/a/9337047) | |
newPath = parentPath + `.${key}`; | |
} else { | |
// Complex identifier: Must be accessed with Bracket notation. | |
newPath = parentPath + `["${key}"]`; | |
} | |
if (nameRegex.test(key)) { | |
console.log(`${newPath}`); | |
} | |
if (typeof value === "object" && value !== null) { | |
_findValues({ [newPath]: value }, nameRegex); | |
} | |
} | |
} | |
_findValues(input, nameRegex); | |
} | |
/* | |
* Usage examples | |
* ============== | |
*/ | |
if (false) { | |
// Use the variable `globalThis`, which is the parent global variable defined | |
// in both web browsers (same as `window`) and Node.js (same as `global`). | |
findValues({ globalThis }, /myValue/); | |
} | |
if (false) { | |
// Any root object or array can be passed to this function. | |
const rootObject = { | |
number: 42, | |
string: "test", | |
"complex-key": { stream1: 1 }, | |
object: { stream2: 2 }, | |
array: [{ openh264: 3 }, { OpenVidu: 4 }], | |
}; | |
findValues({ test: rootObject }, /[oO]pen[vV]idu|[sS]tream|pc/); | |
// Output: | |
// test["complex-key"].stream1 | |
// test.object.stream2 | |
// test.array[1].OpenVidu | |
} | |
if (false) { | |
// This searches through all of Angular values in the OpenVidu Call | |
// application, to find the [RTCPeerConnection](https://developer.mozilla.org/docs/Web/API/RTCPeerConnection) | |
// that corresponds to an active Publisher stream. | |
// In case of OpenVidu Call, this should be stored inside a WebRtcPeer, so the | |
// output should look something like this: | |
// | |
// (... Angular stuff).session.connection.stream.webRtcPeer.pc | |
findValues( | |
{ | |
"window.getAllAngularRootElements()": window.getAllAngularRootElements(), | |
}, | |
/^pc$/ | |
); | |
// Output: | |
// window.getAllAngularRootElements()[0].__ngContext__[10].engine._transitionEngine | |
// ._namespaceLookup["c146-0"].hostElement.__ngContext__[13][8].openviduService | |
// .OV.publishers[0].videos[0].video.__ngContext__[0].__ngContext__[0] | |
// .__ngContext__[0].__ngContext__[3][0].__ngContext__[0].__ngContext__[0] | |
// .__ngContext__[0].__ngContext__[0].__ngContext__[17][4][4][4][4][4][4][4][4][4][4][9][0][0] | |
// .__ngContext__[3][0].__ngContext__[0].__ngContext__[0].__ngContext__[0].__ngContext__[14][9][0][3][4][8][0] | |
// ._lView[13][8][0]._lView[13][8][0]._lView[13][8][0]._lView[13][8] | |
// .session.connection.stream.webRtcPeer.pc | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment