Tampermonkey / tampermonkey

Tampermonkey is the most popular userscript manager, with over 10 million users. It's available for Chrome, Microsoft Edge, Safari, Opera Next, and Firefox.
GNU General Public License v3.0
4.32k stars 426 forks source link

@run-at document-body/document-start may run after setTimeout() #1744

Closed myocytebd closed 1 year ago

myocytebd commented 1 year ago

Expected Behavior

document-body/document-start run before any setTimeout().

Actual Behavior

document-body/document-start may after setTimeout().

Specifications

Script

Webpage:

<!DOCTYPE html
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
    <title>Archiver</title>
    <link rel="stylesheet" type="text/css" href="https://exhentai.org/z/0363/x.css" />
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
    <meta name="robots" content="noindex,nofollow" />
    <link rel="icon" type="image/png" href="/favicon.png" />
    <style type="text/css">
        div#db{width:450px;text-align:center;margin:5px auto auto auto;border:1px solid #000000;background:#4f535b;padding:2px 5px 2px 5px}
    </style>
</head>

<body>
<div id="db"><p>Locating archive server and preparing file for download...</p><p>(this can take several minutes)</p>
<p id="continue">(<a href="..." onclick="gotonext(); return false">Click here if your browser does not continue automatically</a>)</p>
<p>[ <a href="javascript:window.close()">Close</a> ]</p>

<script type="text/javascript">
function gotonext() {
    document.getElementById("continue").innerHTML = "Please wait...";
    document.location = "...";
}
setTimeout("gotonext()", 1);
</script>
</div>
</body>
</html>
// ==UserScript==
// @name         run-at defect
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_getValue
// @match        https://e-hentai.org/archiver.php*
// @match        https://exhentai.org/archiver.php*
// @run-at       document-start
// ==/UserScript==

console.log(`gotonext.0: ${unsafeWindow.gotonext}`);
Object.defineProperty(unsafeWindow, 'gotonext', { get: () => 'dummy', set: (gotonext) => {} });

The UserScript is supposed to always prevent the navigation in gotonext().
However in Firefox, it is at least 9/10 that the navigation continues. Log shows that gotonext is already defined as function when UserScript runs.

In Chrome 111.0.5563.64 (Official Build) (64-bit):

It seems that TamperMonkey wraps UserScript as async, which I would frown upon in case of 'document-start'/'document-body'.
(The target site is NSFW and needs account, so I did not post full link)

derjanb commented 1 year ago

Duplicate of https://github.com/Tampermonkey/tampermonkey/issues/211#issuecomment-317116595 🤷