Closed tdreams2 closed 1 month ago
Cannot read properties of undefined (reading 'classList')
getDislikeButton().classList.contains("style-default-active")
From:
function isVideoDisliked() {
if (isMobile()) {
return (
getDislikeButton().querySelector("button").getAttribute("aria-label") === "true"
);
}
return getDislikeButton().classList.contains("style-default-active") || getDislikeButton().querySelector('button')?.getAttribute('aria-pressed') === 'true';
}
Windows 11:
So I think with this error if I dislike a video, it will not count my dislike through API
Cannot read properties of undefined (reading 'classList')
getDislikeButton().classList.contains("style-default-active")
I'm getting it sometimes on both Windows 10 and Windows 11. Both on:
I think this should be fine since if you do:
function getDislikeButton() {
console.log("getDislikeButton");
const dislikeButton =
getButtons().children[0].tagName ===
"YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER"
? getButtons().children[0].children[1] === undefined
? document.querySelector("#segmented-dislike-button")
: getButtons().children[0].children[1]
: getButtons().children[1];
console.log(dislikeButton);
return dislikeButton;
}
You end up getting what seems like calls to get the buttons until they exist.
ryd.content-script.js:786 getDislikeButton ryd.content-script.js:788 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'children') at getDislikeButton (ryd.content-script.js:788:17) at isVideoDisliked (ryd.content-script.js:488:10) at setState (ryd.content-script.js:604:30) at setInitialState (ryd.content-script.js:637:3) at checkForJS_Finish (ryd.content-script.js:1021:9) getDislikeButton @ ryd.content-script.js:788 ... ryd.content-script.js:786 getDislikeButton ryd.content-script.js:794 <ytd-toggle-button-renderer id="dislike-button" is-shorts class="style-scope ytd-like-button-renderer" vertically-aligned button-renderer="true">… ryd.content-script.js:786 getDislikeButton ryd.content-script.js:794 <ytd-toggle-button-renderer id="dislike-button" is-shorts class="style-scope ytd-like-button-renderer" vertically-aligned button-renderer="true">… ryd.content-script.js:786 getDislikeButton ryd.content-script.js:794 <ytd-toggle-button-renderer id="dislike-button" is-shorts class="style-scope ytd-like-button-renderer" vertically-aligned button-renderer="true">… ryd.content-script.js:786 getDislikeButton ryd.content-script.js:794 <ytd-toggle-button-renderer id="dislike-button" is-shorts class="style-scope ytd-like-button-renderer" vertically-aligned button-renderer="true">… ryd.content-script.js:786 getDislikeButton
Think there is some underlying logic in state where we re-querySelect if we error or something or it might be some mutationobserver implementation that I haven't looked into. If someone has insight into this, let us know.
To summarize: This should be fine 😅.
EDIT: More importantly, when inspecting the service worker's network tab we can see the request succeeding even if we had the error in the console. API is still getting the info it needs.
Think there is some underlying logic in state where we re-querySelect if we error or something or it might be some mutationobserver implementation that I haven't looked into. If someone has insight into this, let us know.
Actually there is a mutationObserver I think and it causing issues
mutationObserver code:
let mutationObserver = new Object();
if (isShorts() && mutationObserver.exists !== true) {
cLog("initializing mutation observer");
mutationObserver.options = {
childList: false,
attributes: true,
subtree: false,
};
mutationObserver.exists = true;
mutationObserver.observer = new MutationObserver(function (
mutationList,
observer
) {
mutationList.forEach((mutation) => {
if (
mutation.type === "attributes" &&
mutation.target.nodeName === "TP-YT-PAPER-BUTTON" &&
mutation.target.id === "button"
) {
// cLog('Short thumb button status changed');
if (mutation.target.getAttribute("aria-pressed") === "true") {
mutation.target.style.color =
mutation.target.parentElement.parentElement.id === "like-button"
? getColorFromTheme(true)
: getColorFromTheme(false);
} else {
mutation.target.style.color = "unset";
}
return;
}
cLog(
"unexpected mutation observer event: " + mutation.target + mutation.type
);
});
});
}
for some reason the MutationObserver doesn't initiate if you produce the error steps above, and the only way to initialize it is by refreshing the page while we are on shorts path
Actually there is a mutationObserver I think and it causing issues
Unless there are more issues than the errors in the console from before, I don't think it's a huge priority but something we should look at next.
This change doesn't really make any sense, does it?
If getLikeButton()
returns something, || getLikeButton().parentNode
is not used.
If getLikeButton()
returns nothing, || getLikeButton().parentNode
will throw an error.
Also, textNodeClone
is not supposed to be the whole like button.
I fixed it locally like this:
const textNodeClone = (getLikeButton().querySelector("button > div[class*='cbox']") || (getLikeButton().querySelector('div > span[role="text"]') || document.querySelector('button > div.yt-spec-button-shape-next__button-text-content > span[role="text"]')).parentNode).cloneNode(true);
Since the like button does not have any <span role="text">
elements anymore for me, I simply use any button element on the page (they all have the same structure).
Fair point. It's interesting to note that just const textNodeClone = getLikeButton().cloneNode(true);
seems to be working for me now also. Do we know when and why the specific selectors work or don't?
In which situations are we using:
getLikeButton().querySelector("button > div[class*='cbox']").cloneNode(true);
getLikeButton().querySelector('div > span[role="text"]').parentNode.cloneNode(true);
document.querySelector('button > div.yt-spec-button-shape-next__button-text-content > span[role="text"]').parentNode.cloneNode(true);
This seems to have been fixed by other PRs, please reopen if experiencing issues with the latest extension version
I changed this line of code in createDislikeTextContainer() function:
const textNodeClone = (getLikeButton().querySelector("button > div[class*='cbox']") || getLikeButton().querySelector('div > span[role="text"]').parentNode).cloneNode(true);
changed to this:
const textNodeClone = (getLikeButton() || getLikeButton().parentNode).cloneNode(true);
Selectors: ("button > div[class*='cbox']") and ('div > span[role="text"]') can't be found on the page