fix: use script/link tag injection in frappe.require to preserve global scope

- Changed frappe.require to use script/link tag injection instead of fetch + IIFE
- This fixes loading of UMD libraries like html5-qrcode that need global scope
- Maintains original behavior: waits for assets to load before callback
- Resolves scanner breakage caused by PR #33973
This commit is contained in:
Sagar Vora 2025-11-23 20:53:16 +05:30
parent 091e12324e
commit ceafcc8790

View file

@ -23,11 +23,28 @@ class AssetManager {
constructor() {
this._executed = [];
this._handlers = {
js: function (txt) {
frappe.dom.eval(txt);
js: (url) => {
return new Promise((resolve) => {
const script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.onload = resolve;
// for backward compatibility, resolve even on error
script.onerror = resolve;
document.head.appendChild(script);
});
},
css: function (txt) {
frappe.dom.set_style(txt);
css: (url) => {
return new Promise((resolve) => {
const link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
link.onload = resolve;
// for backward compatibility, resolve even on error
link.onerror = resolve;
document.head.appendChild(link);
});
},
};
}
@ -77,11 +94,16 @@ class AssetManager {
console.log("localStorage cleared");
}
eval_assets(path, content) {
if (!this._executed.includes(path)) {
this._handlers[this.extn(path)](content);
this._executed.push(path);
load_asset(path, url) {
if (this._executed.includes(path)) {
return Promise.resolve();
}
const ext = this.extn(path);
const handler = this._handlers[ext];
return handler(url).then(() => {
this._executed.push(path);
});
}
execute(items, callback) {
@ -91,8 +113,7 @@ class AssetManager {
const version_string =
frappe.boot.developer_mode || window.dev_server ? Date.now() : window._version_number;
let fetched_assets = {};
async function fetch_item(path) {
let load_promises = items.map((path) => {
let url = new URL(path, window.location.origin);
// Add the version to the URL to bust the cache for non-bundled assets
@ -103,17 +124,12 @@ class AssetManager {
) {
url.searchParams.append("v", version_string);
}
const response = await fetch(url.toString());
fetched_assets[path] = await response.text();
}
return me.load_asset(path, url.toString());
});
frappe.dom.freeze();
const fetch_promises = items.map(fetch_item);
Promise.all(fetch_promises).then(() => {
items.forEach((path) => {
let body = fetched_assets[path];
me.eval_assets(path, body);
});
Promise.all(load_promises).then(() => {
frappe.dom.unfreeze();
callback?.();
});