Fix <sql> silent-failure bug; split /vst into overview + subpage; misc site fixes
- __mysql.cpp: <sql> never checked mysql_real_query's own return code, so a genuine query failure was indistinguishable from "ran fine, zero rows" - <try>/<catch> around a failing <sql> never actually caught anything anywhere. Now throws on a real failure. - spa.js: dynamically re-injected scripts now run in true sequential order (wait for each external script's load event before running the next), fixing checkout's Square card field never building on the first client-side navigation to /checkout (only after a refresh) - async=false alone only orders multiple external scripts relative to each other, it doesn't delay a plain inline sibling. - /vst split into a real overview + /vst/modular1 subpage with a left menu, reusing opensource.page's existing subpage-tier pattern (opensource.menu/main.css's submenuitem-active highlighting, and several other subpage-tier retirements, were already finished earlier this session but never committed - included here too). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
46ef67b735
commit
905fbafa5a
17 files changed
+474
-63
No files matched your search
@@ -127,19 +127,43 @@
|
||||
// a client-side SPA swap (e.g. clicking "Check Out") instead of a
|
||||
// full reload; only worked by accident on a fresh /checkout load.
|
||||
// Re-creating each script element makes the browser actually run
|
||||
// it. async=false on src="" ones preserves normal in-order
|
||||
// execution (dynamically-inserted external scripts default to
|
||||
// async otherwise), matching how a real page load would run them.
|
||||
// it. A prior fix set async=false on src="" ones, but that only
|
||||
// orders MULTIPLE external scripts relative to each other - it
|
||||
// does nothing to delay a plain inline script sitting right after
|
||||
// one, which still runs immediately on insertion regardless of a
|
||||
// sibling's in-flight fetch. checkout.page is exactly that shape
|
||||
// (an external Square SDK <script src> immediately followed by an
|
||||
// inline script calling Square.payments(...)): on a client-side
|
||||
// SPA swap the inline script ran before Square had actually
|
||||
// finished downloading, throwing "Square is not defined" inside an
|
||||
// async function with no visible catch, leaving the card container
|
||||
// permanently empty - reported as "checkout's card field doesn't
|
||||
// build the first time, only after a refresh" (a real full page
|
||||
// load's parser-inserted <script src> blocks until loaded before
|
||||
// the next tag runs, which a dynamically re-created one does not
|
||||
// do on its own). Fixed by actually waiting for each external
|
||||
// script's load/error event before moving on to the next one,
|
||||
// rather than trusting async=false's narrower ordering guarantee -
|
||||
// reproduced the failure and confirmed the fix against a real
|
||||
// artificially-delayed script load before deploying.
|
||||
var scripts = content.querySelectorAll('script');
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
var old = scripts[i];
|
||||
var scriptList = [];
|
||||
for (var i = 0; i < scripts.length; i++) scriptList.push(scripts[i]);
|
||||
(function runScript(index) {
|
||||
if (index >= scriptList.length) return;
|
||||
var old = scriptList[index];
|
||||
var fresh = document.createElement('script');
|
||||
for (var j = 0; j < old.attributes.length; j++)
|
||||
fresh.setAttribute(old.attributes[j].name, old.attributes[j].value);
|
||||
if (fresh.src) fresh.async = false;
|
||||
fresh.textContent = old.textContent;
|
||||
old.parentNode.replaceChild(fresh, old);
|
||||
}
|
||||
if (fresh.src) {
|
||||
fresh.onload = fresh.onerror = function() { runScript(index + 1); };
|
||||
old.parentNode.replaceChild(fresh, old);
|
||||
} else {
|
||||
old.parentNode.replaceChild(fresh, old);
|
||||
runScript(index + 1);
|
||||
}
|
||||
})(0);
|
||||
// #_spa_panelmenu carries the CURRENT page's own side-menu markup
|
||||
// (mainpagetemplate.jet renders it into every fragment response
|
||||
// specifically so this can pull it out) - extracted from the
|
||||
|
||||
Reference in new issue
Block a user