Skip to content

Instantly share code, notes, and snippets.

@odony
Created June 30, 2026 17:16
Show Gist options
  • Select an option

  • Save odony/4fb16418a20c32c1527474e9885dd5d3 to your computer and use it in GitHub Desktop.

Select an option

Save odony/4fb16418a20c32c1527474e9885dd5d3 to your computer and use it in GitHub Desktop.
fix_turnstile_june2026.patch
diff --git addons/website_cf_turnstile/static/src/interactions/turnstile.js addons/website_cf_turnstile/static/src/interactions/turnstile.js
index 8008f9bb38df..c63fc0b912d1 100644
--- addons/website_cf_turnstile/static/src/interactions/turnstile.js
+++ addons/website_cf_turnstile/static/src/interactions/turnstile.js
@@ -3,16 +3,23 @@ import { session } from "@web/session";
export class TurnStile {
static turnstileURL = "https://challenges.cloudflare.com/turnstile/v0/api.js";
+ static nextId = 0;
constructor(action) {
const cf = new URLSearchParams(window.location.search).get("cf");
const mode = cf == "show" ? "always" : "interaction-only";
+
+ // unique per-widget callback names to support multiple widgets on same page
+ const id = TurnStile.nextId++;
+ const successCbName = `turnstileSuccess_${id}`;
+ const becomeVisibleCbName = `turnstileBecomeVisible_${id}`;
+
const turnstileContainer = renderToElement("website_cf_turnstile.turnstile_container", {
action: action,
appearance: mode,
- beforeInteractiveGlobalCallback: "turnstileBecomeVisible",
+ beforeInteractiveGlobalCallback: becomeVisibleCbName,
errorGlobalCallback: "throwTurnstileErrorCode",
- executeGlobalCallback: "turnstileSuccess",
+ executeGlobalCallback: successCbName,
sitekey: session.turnstile_site_key,
style: "display: none;",
});
@@ -24,9 +31,9 @@ export class TurnStile {
error.code = code;
throw error;
};
- // `this` is bound to the turnstile widget calling the callback
- globalThis.turnstileSuccess = function () {
- const form = this.wrapper.closest("form") || this.wrapper.parentElement.parentElement;
+ globalThis[successCbName] = function (token) {
+ const form = turnstileContainer.closest("form")
+ || turnstileContainer.parentElement?.parentElement;
const buttons = form.querySelectorAll(".cf_form_disabled");
for (const button of buttons) {
button.classList.remove("disabled", "cf_form_disabled");
@@ -38,8 +45,7 @@ export class TurnStile {
inputValidation.required = false;
};
// unhide if interaction is needed
- globalThis.turnstileBecomeVisible = function () {
- const turnstileContainer = this.wrapper.parentElement;
+ globalThis[becomeVisibleCbName] = function () {
turnstileContainer.style.display = "";
};
// avoid modifying shape of return, for stable compatibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment