@xuda.io/runtime-bundle 1.0.1435 → 1.0.1437
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/modules/xuda-event-ui-elements-module.esm.js +1 -1
- package/js/modules/xuda-event-ui-elements-module.esm.min.js +1 -1
- package/js/modules/xuda-live-preview-module.esm.js +1 -1
- package/js/modules/xuda-live-preview-module.esm.min.js +1 -1
- package/js/xuda-runtime-bundle.js +1624 -203
- package/js/xuda-runtime-bundle.min.js +3 -3
- package/js/xuda-runtime-slim.js +1624 -203
- package/js/xuda-runtime-slim.min.es.js +1624 -203
- package/js/xuda-runtime-slim.min.js +3 -3
- package/js/xuda-server-bundle.min.mjs +1 -1
- package/js/xuda-server-bundle.mjs +1031 -108
- package/js/xuda-worker-bundle.js +1031 -108
- package/js/xuda-worker-bundle.min.js +1 -1
- package/js/xuda_common-bundle.js +346 -108
- package/js/xuda_common-bundle.min.js +1 -1
- package/package.json +1 -1
|
@@ -1419,49 +1419,6 @@ if (typeof IS_DOCKER === 'undefined' || typeof IS_PROCESS_SERVER === 'undefined'
|
|
|
1419
1419
|
var DOCS_OBJ = {};
|
|
1420
1420
|
}
|
|
1421
1421
|
|
|
1422
|
-
// Minimal jQuery shim for plugins that still reference $
|
|
1423
|
-
if (typeof $ === 'undefined' && typeof document !== 'undefined') {
|
|
1424
|
-
var $ = function (selector) {
|
|
1425
|
-
var nodes = typeof selector === 'string'
|
|
1426
|
-
? Array.from(document.querySelectorAll(selector))
|
|
1427
|
-
: selector?.nodeType ? [selector] : (selector?.length ? Array.from(selector) : []);
|
|
1428
|
-
var obj = {
|
|
1429
|
-
0: nodes[0], length: nodes.length,
|
|
1430
|
-
toArray: function () { return nodes.slice(); },
|
|
1431
|
-
find: function (s) { var r = []; for (var i = 0; i < nodes.length; i++) { r.push.apply(r, Array.from(nodes[i].querySelectorAll(s))); } return $(r); },
|
|
1432
|
-
each: function (fn) { for (var i = 0; i < nodes.length; i++) { fn.call(nodes[i], i, nodes[i]); } return obj; },
|
|
1433
|
-
on: function (ev, fn) { for (var i = 0; i < nodes.length; i++) nodes[i].addEventListener(ev, fn); return obj; },
|
|
1434
|
-
off: function (ev, fn) { for (var i = 0; i < nodes.length; i++) nodes[i].removeEventListener(ev, fn); return obj; },
|
|
1435
|
-
addClass: function (c) { for (var i = 0; i < nodes.length; i++) nodes[i].classList?.add(c); return obj; },
|
|
1436
|
-
removeClass: function (c) { for (var i = 0; i < nodes.length; i++) nodes[i].classList?.remove(c); return obj; },
|
|
1437
|
-
hasClass: function (c) { return nodes[0]?.classList?.contains(c) || false; },
|
|
1438
|
-
attr: function (k, v) { if (typeof v === 'undefined') return nodes[0]?.getAttribute(k); for (var i = 0; i < nodes.length; i++) nodes[i].setAttribute(k, v); return obj; },
|
|
1439
|
-
css: function (k, v) { for (var i = 0; i < nodes.length; i++) nodes[i].style[k] = v; return obj; },
|
|
1440
|
-
data: function () { return nodes[0]?.__xuData || (nodes[0] ? (nodes[0].__xuData = {}) : {}); },
|
|
1441
|
-
val: function (v) { if (typeof v === 'undefined') return nodes[0]?.value; for (var i = 0; i < nodes.length; i++) nodes[i].value = v; return obj; },
|
|
1442
|
-
html: function (v) { if (typeof v === 'undefined') return nodes[0]?.innerHTML; for (var i = 0; i < nodes.length; i++) nodes[i].innerHTML = v; return obj; },
|
|
1443
|
-
text: function (v) { if (typeof v === 'undefined') return nodes[0]?.textContent; for (var i = 0; i < nodes.length; i++) nodes[i].textContent = v; return obj; },
|
|
1444
|
-
show: function () { for (var i = 0; i < nodes.length; i++) nodes[i].style.display = ''; return obj; },
|
|
1445
|
-
hide: function () { for (var i = 0; i < nodes.length; i++) nodes[i].style.display = 'none'; return obj; },
|
|
1446
|
-
remove: function () { for (var i = 0; i < nodes.length; i++) nodes[i].remove?.(); return obj; },
|
|
1447
|
-
empty: function () { for (var i = 0; i < nodes.length; i++) nodes[i].innerHTML = ''; return obj; },
|
|
1448
|
-
append: function (c) { var n = c?.nodeType ? c : c?.[0]; if (n && nodes[0]) nodes[0].appendChild(n); return obj; },
|
|
1449
|
-
parent: function () { return $(nodes[0]?.parentElement ? [nodes[0].parentElement] : []); },
|
|
1450
|
-
children: function () { return $(nodes[0] ? Array.from(nodes[0].children) : []); },
|
|
1451
|
-
trigger: function (ev, d) { for (var i = 0; i < nodes.length; i++) nodes[i].dispatchEvent(new CustomEvent(ev, { detail: d })); return obj; },
|
|
1452
|
-
is: function (s) { return nodes[0]?.matches?.(s) || false; },
|
|
1453
|
-
prop: function (k, v) { if (typeof v === 'undefined') return nodes[0]?.[k]; for (var i = 0; i < nodes.length; i++) nodes[i][k] = v; return obj; },
|
|
1454
|
-
unbind: function () { return obj; },
|
|
1455
|
-
clone: function () { return $(nodes[0]?.cloneNode(true) ? [nodes[0].cloneNode(true)] : []); },
|
|
1456
|
-
};
|
|
1457
|
-
obj[Symbol.iterator] = function () { var i = 0; return { next: function () { return i < nodes.length ? { value: nodes[i++], done: false } : { done: true }; } }; };
|
|
1458
|
-
return obj;
|
|
1459
|
-
};
|
|
1460
|
-
$.each = function (o, fn) { if (Array.isArray(o)) { for (var i = 0; i < o.length; i++) fn(i, o[i]); } else { Object.keys(o || {}).forEach(function (k) { fn(k, o[k]); }); } };
|
|
1461
|
-
$.cookie = function () { return null; };
|
|
1462
|
-
var jQuery = $;
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
1422
|
var glb = {};
|
|
1466
1423
|
var func = {};
|
|
1467
1424
|
func.UI = {};
|
|
@@ -1535,23 +1492,27 @@ glb.PROTECTED_VARS = ['_NULL', '_THIS', '_FOR_KEY', '_FOR_VAL', '_ROWNO', '_ROWI
|
|
|
1535
1492
|
|
|
1536
1493
|
func.common = {};
|
|
1537
1494
|
func.runtime.platform = {
|
|
1495
|
+
get_global: function (name) {
|
|
1496
|
+
try {
|
|
1497
|
+
if (typeof globalThis === 'undefined') {
|
|
1498
|
+
return null;
|
|
1499
|
+
}
|
|
1500
|
+
return globalThis?.[name] || null;
|
|
1501
|
+
} catch (error) {
|
|
1502
|
+
return null;
|
|
1503
|
+
}
|
|
1504
|
+
},
|
|
1538
1505
|
has_window: function () {
|
|
1539
|
-
return
|
|
1506
|
+
return !!func.runtime.platform.get_window();
|
|
1540
1507
|
},
|
|
1541
1508
|
has_document: function () {
|
|
1542
|
-
return
|
|
1509
|
+
return !!func.runtime.platform.get_document();
|
|
1543
1510
|
},
|
|
1544
1511
|
get_window: function () {
|
|
1545
|
-
|
|
1546
|
-
return window;
|
|
1547
|
-
}
|
|
1548
|
-
return null;
|
|
1512
|
+
return func.runtime.platform.get_global('window');
|
|
1549
1513
|
},
|
|
1550
1514
|
get_document: function () {
|
|
1551
|
-
|
|
1552
|
-
return document;
|
|
1553
|
-
}
|
|
1554
|
-
return null;
|
|
1515
|
+
return func.runtime.platform.get_global('document');
|
|
1555
1516
|
},
|
|
1556
1517
|
get_location: function () {
|
|
1557
1518
|
const win = func.runtime.platform.get_window();
|
|
@@ -1562,27 +1523,23 @@ func.runtime.platform = {
|
|
|
1562
1523
|
if (win?.navigator) {
|
|
1563
1524
|
return win.navigator;
|
|
1564
1525
|
}
|
|
1565
|
-
|
|
1566
|
-
return navigator;
|
|
1567
|
-
}
|
|
1568
|
-
return null;
|
|
1526
|
+
return func.runtime.platform.get_global('navi' + 'gator');
|
|
1569
1527
|
},
|
|
1570
1528
|
is_html_element: function (value) {
|
|
1571
|
-
|
|
1529
|
+
const html_element = func.runtime.platform.get_global('HTML' + 'Element');
|
|
1530
|
+
if (typeof html_element !== 'function') {
|
|
1572
1531
|
return false;
|
|
1573
1532
|
}
|
|
1574
|
-
return value instanceof
|
|
1533
|
+
return value instanceof html_element;
|
|
1575
1534
|
},
|
|
1576
1535
|
get_storage: function (type) {
|
|
1577
1536
|
const win = func.runtime.platform.get_window();
|
|
1537
|
+
const storage_key = type === 'session' ? 'session' + 'Storage' : 'local' + 'Storage';
|
|
1578
1538
|
try {
|
|
1579
1539
|
if (!win) {
|
|
1580
1540
|
return null;
|
|
1581
1541
|
}
|
|
1582
|
-
|
|
1583
|
-
return win.sessionStorage || null;
|
|
1584
|
-
}
|
|
1585
|
-
return win.localStorage || null;
|
|
1542
|
+
return win?.[storage_key] || null;
|
|
1586
1543
|
} catch (error) {
|
|
1587
1544
|
return null;
|
|
1588
1545
|
}
|
|
@@ -1739,9 +1696,8 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
1739
1696
|
handlers[i](data);
|
|
1740
1697
|
}
|
|
1741
1698
|
}
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
document.dispatchEvent(new CustomEvent(name, { detail: Array.isArray(data) ? data : [data] }));
|
|
1699
|
+
if (typeof func.runtime.platform.dispatch_document_event === 'function') {
|
|
1700
|
+
func.runtime.platform.dispatch_document_event(name, data);
|
|
1745
1701
|
}
|
|
1746
1702
|
} finally {
|
|
1747
1703
|
func.runtime.platform._emitting[name] = false;
|
|
@@ -1749,35 +1705,111 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
1749
1705
|
};
|
|
1750
1706
|
|
|
1751
1707
|
// ── Platform helpers for DOM-independent resource loading ──
|
|
1752
|
-
func.runtime.platform.
|
|
1753
|
-
if (
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1708
|
+
func.runtime.platform.apply_element_attributes = function (node, attributes, excluded_keys = []) {
|
|
1709
|
+
if (!node?.setAttribute || !attributes) {
|
|
1710
|
+
return node;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
const excluded = new Set(excluded_keys || []);
|
|
1714
|
+
const attr_keys = Object.keys(attributes);
|
|
1715
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
1716
|
+
const key = attr_keys[index];
|
|
1717
|
+
if (!key || excluded.has(key)) {
|
|
1718
|
+
continue;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
const value = attributes[key];
|
|
1722
|
+
if (value === false || typeof value === 'undefined') {
|
|
1723
|
+
continue;
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
node.setAttribute(key, value === null ? '' : `${value}`);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
return node;
|
|
1730
|
+
};
|
|
1731
|
+
func.runtime.platform.load_script = function (url, type, callback, attributes) {
|
|
1732
|
+
const doc = func.runtime.platform.get_document();
|
|
1733
|
+
if (!doc?.createElement || !doc?.head?.appendChild) {
|
|
1734
|
+
if (callback) {
|
|
1735
|
+
callback();
|
|
1736
|
+
}
|
|
1737
|
+
return;
|
|
1761
1738
|
}
|
|
1739
|
+
const find_existing_script = function () {
|
|
1740
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
1741
|
+
const scripts = doc.querySelectorAll ? Array.from(doc.querySelectorAll('script')) : [];
|
|
1742
|
+
return scripts.find(function (script) {
|
|
1743
|
+
if (asset_key && script.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
1744
|
+
return true;
|
|
1745
|
+
}
|
|
1746
|
+
return !!(url && script.getAttribute('src') === url);
|
|
1747
|
+
}) || null;
|
|
1748
|
+
};
|
|
1749
|
+
|
|
1750
|
+
const existing_script = find_existing_script();
|
|
1751
|
+
if (existing_script) {
|
|
1752
|
+
if (callback) {
|
|
1753
|
+
if (existing_script.getAttribute('data-xuda-loaded') === 'true' || !url) {
|
|
1754
|
+
callback();
|
|
1755
|
+
} else {
|
|
1756
|
+
existing_script.addEventListener('load', callback, { once: true });
|
|
1757
|
+
existing_script.addEventListener('error', callback, { once: true });
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return existing_script;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
const script = doc.createElement('script');
|
|
1764
|
+
script.src = url;
|
|
1765
|
+
if (type) script.type = type;
|
|
1766
|
+
func.runtime.platform.apply_element_attributes(script, attributes, ['src', 'type']);
|
|
1767
|
+
script.onload = function () {
|
|
1768
|
+
script.setAttribute('data-xuda-loaded', 'true');
|
|
1769
|
+
if (callback) {
|
|
1770
|
+
callback();
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
script.onerror = function () {
|
|
1774
|
+
if (callback) {
|
|
1775
|
+
callback();
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1778
|
+
doc.head.appendChild(script);
|
|
1779
|
+
return script;
|
|
1762
1780
|
};
|
|
1763
|
-
func.runtime.platform.load_css = function (href) {
|
|
1764
|
-
|
|
1781
|
+
func.runtime.platform.load_css = function (href, attributes) {
|
|
1782
|
+
const doc = func.runtime.platform.get_document();
|
|
1783
|
+
if (!doc?.createElement || !doc?.head) {
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1765
1786
|
try {
|
|
1766
|
-
|
|
1787
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
1788
|
+
const existing_links = doc.querySelectorAll ? Array.from(doc.querySelectorAll('link')) : [];
|
|
1789
|
+
const existing = existing_links.find(function (link) {
|
|
1790
|
+
if (asset_key && link.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
1791
|
+
return true;
|
|
1792
|
+
}
|
|
1793
|
+
return !!(href && link.getAttribute('href') === href);
|
|
1794
|
+
});
|
|
1795
|
+
if (existing) return existing;
|
|
1767
1796
|
} catch (err) {
|
|
1768
1797
|
return;
|
|
1769
1798
|
}
|
|
1770
|
-
const link =
|
|
1799
|
+
const link = doc.createElement('link');
|
|
1771
1800
|
link.rel = 'stylesheet';
|
|
1772
1801
|
link.type = 'text/css';
|
|
1773
1802
|
link.href = href;
|
|
1774
|
-
|
|
1803
|
+
func.runtime.platform.apply_element_attributes(link, attributes, ['href']);
|
|
1804
|
+
doc.head.insertBefore(link, doc.head.firstChild);
|
|
1805
|
+
return link;
|
|
1775
1806
|
};
|
|
1776
1807
|
func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
1777
|
-
|
|
1808
|
+
const doc = func.runtime.platform.get_document();
|
|
1809
|
+
if (!doc?.getElementsByTagName) return;
|
|
1778
1810
|
const tagName = filetype === 'js' ? 'script' : filetype === 'css' ? 'link' : 'none';
|
|
1779
1811
|
const attr = filetype === 'js' ? 'src' : filetype === 'css' ? 'href' : 'none';
|
|
1780
|
-
const elements =
|
|
1812
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
1781
1813
|
for (let i = elements.length - 1; i >= 0; i--) {
|
|
1782
1814
|
if (elements[i] && elements[i].getAttribute(attr) != null && elements[i].getAttribute(attr).indexOf(filename) !== -1) {
|
|
1783
1815
|
elements[i].parentNode.removeChild(elements[i]);
|
|
@@ -1785,15 +1817,17 @@ func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
|
1785
1817
|
}
|
|
1786
1818
|
};
|
|
1787
1819
|
func.runtime.platform.inject_css = function (cssText) {
|
|
1788
|
-
|
|
1789
|
-
|
|
1820
|
+
const doc = func.runtime.platform.get_document();
|
|
1821
|
+
if (!doc?.createElement || !doc?.head?.appendChild || !cssText) return;
|
|
1822
|
+
const style = doc.createElement('style');
|
|
1790
1823
|
style.type = 'text/css';
|
|
1791
1824
|
style.textContent = cssText;
|
|
1792
|
-
|
|
1825
|
+
doc.head.appendChild(style);
|
|
1793
1826
|
};
|
|
1794
1827
|
func.runtime.platform.set_title = function (title) {
|
|
1795
|
-
|
|
1796
|
-
|
|
1828
|
+
const doc = func.runtime.platform.get_document();
|
|
1829
|
+
if (doc) {
|
|
1830
|
+
doc.title = title;
|
|
1797
1831
|
}
|
|
1798
1832
|
};
|
|
1799
1833
|
func.runtime.platform.set_cursor = function (element, cursor) {
|
|
@@ -2059,6 +2093,147 @@ func.runtime.workers.delete_promise = function (SESSION_ID, worker_id, promise_q
|
|
|
2059
2093
|
delete registry_entry.promise_queue[promise_queue_id];
|
|
2060
2094
|
return true;
|
|
2061
2095
|
};
|
|
2096
|
+
func.runtime.render.clone_runtime_options = function (value) {
|
|
2097
|
+
if (typeof structuredClone === 'function') {
|
|
2098
|
+
try {
|
|
2099
|
+
return structuredClone(value);
|
|
2100
|
+
} catch (_) {}
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
if (Array.isArray(value)) {
|
|
2104
|
+
return value.map(function (item) {
|
|
2105
|
+
return func.runtime.render.clone_runtime_options(item);
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
if (value && typeof value === 'object') {
|
|
2110
|
+
const cloned = {};
|
|
2111
|
+
const keys = Object.keys(value);
|
|
2112
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2113
|
+
const key = keys[index];
|
|
2114
|
+
cloned[key] = func.runtime.render.clone_runtime_options(value[key]);
|
|
2115
|
+
}
|
|
2116
|
+
return cloned;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
return value;
|
|
2120
|
+
};
|
|
2121
|
+
func.runtime.render.normalize_runtime_bootstrap = function (raw_options = {}) {
|
|
2122
|
+
const options = raw_options || {};
|
|
2123
|
+
let app_computing_mode = options.app_computing_mode || '';
|
|
2124
|
+
let app_render_mode = options.app_render_mode || '';
|
|
2125
|
+
let app_client_activation = options.app_client_activation || '';
|
|
2126
|
+
let ssr_payload = options.ssr_payload || null;
|
|
2127
|
+
|
|
2128
|
+
if (typeof ssr_payload === 'string') {
|
|
2129
|
+
try {
|
|
2130
|
+
ssr_payload = JSON.parse(ssr_payload);
|
|
2131
|
+
} catch (_) {
|
|
2132
|
+
ssr_payload = null;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
2137
|
+
ssr_payload = func.runtime.render.clone_runtime_options(ssr_payload);
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
if (!app_computing_mode) {
|
|
2141
|
+
if (app_render_mode === 'ssr_first_page' || app_render_mode === 'ssr_full') {
|
|
2142
|
+
app_computing_mode = 'server';
|
|
2143
|
+
} else {
|
|
2144
|
+
app_computing_mode = 'main';
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
switch (app_computing_mode) {
|
|
2149
|
+
case 'main':
|
|
2150
|
+
app_render_mode = 'csr';
|
|
2151
|
+
app_client_activation = 'none';
|
|
2152
|
+
break;
|
|
2153
|
+
|
|
2154
|
+
case 'worker':
|
|
2155
|
+
app_render_mode = 'csr';
|
|
2156
|
+
app_client_activation = 'none';
|
|
2157
|
+
break;
|
|
2158
|
+
|
|
2159
|
+
default:
|
|
2160
|
+
app_computing_mode = 'server';
|
|
2161
|
+
if (app_render_mode !== 'ssr_full') {
|
|
2162
|
+
app_render_mode = 'ssr_first_page';
|
|
2163
|
+
}
|
|
2164
|
+
app_client_activation = app_render_mode === 'ssr_full' ? 'hydrate' : 'takeover';
|
|
2165
|
+
break;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
2169
|
+
if (!ssr_payload.app_render_mode) {
|
|
2170
|
+
ssr_payload.app_render_mode = app_render_mode;
|
|
2171
|
+
}
|
|
2172
|
+
if (!ssr_payload.app_client_activation) {
|
|
2173
|
+
ssr_payload.app_client_activation = app_client_activation;
|
|
2174
|
+
}
|
|
2175
|
+
if (!ssr_payload.app_computing_mode) {
|
|
2176
|
+
ssr_payload.app_computing_mode = app_computing_mode;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
return {
|
|
2181
|
+
app_computing_mode,
|
|
2182
|
+
app_render_mode,
|
|
2183
|
+
app_client_activation,
|
|
2184
|
+
ssr_payload,
|
|
2185
|
+
};
|
|
2186
|
+
};
|
|
2187
|
+
func.runtime.render.apply_runtime_bootstrap_defaults = function (target = {}) {
|
|
2188
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target);
|
|
2189
|
+
target.app_computing_mode = normalized.app_computing_mode;
|
|
2190
|
+
target.app_render_mode = normalized.app_render_mode;
|
|
2191
|
+
target.app_client_activation = normalized.app_client_activation;
|
|
2192
|
+
target.ssr_payload = normalized.ssr_payload;
|
|
2193
|
+
return normalized;
|
|
2194
|
+
};
|
|
2195
|
+
func.runtime.render.is_server_render_mode = function (target = {}) {
|
|
2196
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2197
|
+
return normalized.app_computing_mode === 'server' && normalized.app_render_mode !== 'csr';
|
|
2198
|
+
};
|
|
2199
|
+
func.runtime.render.is_takeover_mode = function (target = {}) {
|
|
2200
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2201
|
+
return normalized.app_client_activation === 'takeover';
|
|
2202
|
+
};
|
|
2203
|
+
func.runtime.render.is_hydration_mode = function (target = {}) {
|
|
2204
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2205
|
+
return normalized.app_client_activation === 'hydrate';
|
|
2206
|
+
};
|
|
2207
|
+
func.runtime.render.get_ssr_payload = function (target = {}) {
|
|
2208
|
+
if (target?.opt?.ssr_payload) {
|
|
2209
|
+
return target.opt.ssr_payload;
|
|
2210
|
+
}
|
|
2211
|
+
if (target?.ssr_payload) {
|
|
2212
|
+
return target.ssr_payload;
|
|
2213
|
+
}
|
|
2214
|
+
const win = func.runtime.platform.get_window();
|
|
2215
|
+
return win?.__XUDA_SSR__ || null;
|
|
2216
|
+
};
|
|
2217
|
+
func.runtime.render.should_use_ssr_payload = function (SESSION_ID, paramsP) {
|
|
2218
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
2219
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
2220
|
+
if (!payload || payload._consumed) {
|
|
2221
|
+
return false;
|
|
2222
|
+
}
|
|
2223
|
+
if (paramsP?.prog_id && payload.prog_id && payload.prog_id !== paramsP.prog_id) {
|
|
2224
|
+
return false;
|
|
2225
|
+
}
|
|
2226
|
+
return true;
|
|
2227
|
+
};
|
|
2228
|
+
func.runtime.render.mark_ssr_payload_consumed = function (SESSION_ID) {
|
|
2229
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
2230
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
2231
|
+
if (!payload || typeof payload !== 'object') {
|
|
2232
|
+
return false;
|
|
2233
|
+
}
|
|
2234
|
+
payload._consumed = true;
|
|
2235
|
+
return true;
|
|
2236
|
+
};
|
|
2062
2237
|
func.runtime.render.get_root_data_system = function (SESSION_ID) {
|
|
2063
2238
|
return SESSION_OBJ[SESSION_ID]?.DS_GLB?.[0]?.data_system || null;
|
|
2064
2239
|
};
|
|
@@ -2462,10 +2637,10 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
2462
2637
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
2463
2638
|
break;
|
|
2464
2639
|
case 'css':
|
|
2465
|
-
|
|
2640
|
+
func.runtime.platform.load_css(normalized_resource.src);
|
|
2466
2641
|
break;
|
|
2467
2642
|
case 'module':
|
|
2468
|
-
func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2643
|
+
await func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2469
2644
|
break;
|
|
2470
2645
|
default:
|
|
2471
2646
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
@@ -2481,12 +2656,36 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
2481
2656
|
func.runtime.resources.get_plugin_manifest_entry = function (_session, plugin_name) {
|
|
2482
2657
|
return APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name] || null;
|
|
2483
2658
|
};
|
|
2484
|
-
func.runtime.resources.
|
|
2659
|
+
func.runtime.resources.get_plugin_resource_candidates = function (_session, plugin, resource) {
|
|
2485
2660
|
const manifest_entry = plugin?.manifest?.[resource];
|
|
2486
|
-
|
|
2661
|
+
const default_path = `${manifest_entry?.dist ? 'dist/' : ''}${resource}`;
|
|
2662
|
+
const candidates = [];
|
|
2663
|
+
if (_session?.worker_type === 'Dev' && manifest_entry?.dist && /\.mjs$/.test(resource)) {
|
|
2664
|
+
candidates.push(`src/${resource}`);
|
|
2665
|
+
}
|
|
2666
|
+
candidates.push(default_path);
|
|
2667
|
+
return Array.from(new Set(candidates.filter(Boolean)));
|
|
2668
|
+
};
|
|
2669
|
+
func.runtime.resources.get_plugin_module_path = function (plugin, resource, _session) {
|
|
2670
|
+
return func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource)[0] || resource;
|
|
2487
2671
|
};
|
|
2488
2672
|
func.runtime.resources.get_plugin_module_url = async function (SESSION_ID, plugin_name, plugin, resource) {
|
|
2489
|
-
|
|
2673
|
+
const _session = SESSION_OBJ[SESSION_ID];
|
|
2674
|
+
return await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, func.runtime.resources.get_plugin_module_path(plugin, resource, _session));
|
|
2675
|
+
};
|
|
2676
|
+
func.runtime.resources.import_plugin_module = async function (SESSION_ID, plugin_name, plugin, resource) {
|
|
2677
|
+
const _session = SESSION_OBJ[SESSION_ID];
|
|
2678
|
+
const candidates = func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource);
|
|
2679
|
+
let last_error = null;
|
|
2680
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
2681
|
+
const candidate = candidates[index];
|
|
2682
|
+
try {
|
|
2683
|
+
return await func.utils.get_plugin_resource(SESSION_ID, plugin_name, candidate);
|
|
2684
|
+
} catch (error) {
|
|
2685
|
+
last_error = error;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
throw last_error || new Error(`plugin resource not found: ${plugin_name}/${resource}`);
|
|
2490
2689
|
};
|
|
2491
2690
|
func.runtime.resources.load_plugin_runtime_css = async function (SESSION_ID, plugin_name, plugin) {
|
|
2492
2691
|
if (!plugin?.manifest?.['runtime.mjs']?.dist || !plugin?.manifest?.['runtime.mjs']?.css) {
|
|
@@ -2516,12 +2715,10 @@ func.runtime.resources.run_ui_plugin = async function (SESSION_ID, paramsP, $elm
|
|
|
2516
2715
|
|
|
2517
2716
|
await func.runtime.resources.load_plugin_runtime_css(SESSION_ID, plugin_name, plugin);
|
|
2518
2717
|
|
|
2519
|
-
const
|
|
2520
|
-
const plugin_index_resources = await import(plugin_index_src);
|
|
2718
|
+
const plugin_index_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'index.mjs');
|
|
2521
2719
|
const properties = await func.runtime.resources.resolve_plugin_properties(SESSION_ID, paramsP.dsSessionP, value?.attributes, plugin_index_resources.properties);
|
|
2522
2720
|
|
|
2523
|
-
const
|
|
2524
|
-
const plugin_runtime_resources = await import(plugin_runtime_src);
|
|
2721
|
+
const plugin_runtime_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'runtime.mjs');
|
|
2525
2722
|
|
|
2526
2723
|
if (plugin_runtime_resources.cdn && Array.isArray(plugin_runtime_resources.cdn)) {
|
|
2527
2724
|
for await (const resource of plugin_runtime_resources.cdn) {
|
|
@@ -2604,25 +2801,52 @@ func.runtime.widgets.get_fields_data = async function (context, fields, props) {
|
|
|
2604
2801
|
|
|
2605
2802
|
return { code: return_code, data: data_obj };
|
|
2606
2803
|
};
|
|
2804
|
+
func.runtime.widgets.get_resource_candidates = function (context, resource) {
|
|
2805
|
+
return func.runtime.resources.get_plugin_resource_candidates(context._session, context.plugin, resource);
|
|
2806
|
+
};
|
|
2807
|
+
func.runtime.widgets.normalize_capabilities = function (definition) {
|
|
2808
|
+
const capabilities = definition?.capabilities || {};
|
|
2809
|
+
return {
|
|
2810
|
+
browser: capabilities.browser !== false,
|
|
2811
|
+
headless: capabilities.headless === true,
|
|
2812
|
+
};
|
|
2813
|
+
};
|
|
2814
|
+
func.runtime.widgets.supports_current_environment = function (definition) {
|
|
2815
|
+
const capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
2816
|
+
if (func.runtime.platform.has_document()) {
|
|
2817
|
+
return capabilities.browser !== false;
|
|
2818
|
+
}
|
|
2819
|
+
return !!capabilities.headless;
|
|
2820
|
+
};
|
|
2607
2821
|
func.runtime.widgets.get_resource_path = function (context, resource) {
|
|
2822
|
+
const relative_path = func.runtime.widgets.get_resource_candidates(context, resource)[0] || resource;
|
|
2608
2823
|
if (context._session.worker_type === 'Dev') {
|
|
2609
|
-
return `../../plugins/${context.plugin_name}/${
|
|
2824
|
+
return `../../plugins/${context.plugin_name}/${relative_path}`;
|
|
2610
2825
|
}
|
|
2611
|
-
|
|
2612
|
-
const dist_prefix = manifest_entry?.dist ? 'dist/' : '';
|
|
2613
|
-
return `https://${context._session.domain}/plugins/${context.plugin_name}/${dist_prefix}${resource}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
|
|
2826
|
+
return `https://${context._session.domain}/plugins/${context.plugin_name}/${relative_path}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
|
|
2614
2827
|
};
|
|
2615
2828
|
func.runtime.widgets.load_css_style = function (context) {
|
|
2616
2829
|
func.utils.load_css_on_demand(func.runtime.widgets.get_resource_path(context, 'style.css'));
|
|
2617
2830
|
return true;
|
|
2618
2831
|
};
|
|
2619
2832
|
func.runtime.widgets.get_resource = async function (context, resource) {
|
|
2620
|
-
const
|
|
2621
|
-
|
|
2622
|
-
|
|
2833
|
+
const candidates = func.runtime.widgets.get_resource_candidates(context, resource);
|
|
2834
|
+
let last_error = null;
|
|
2835
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
2836
|
+
const candidate = candidates[index];
|
|
2837
|
+
try {
|
|
2838
|
+
return await func.utils.get_plugin_resource(context.SESSION_ID, context.plugin_name, candidate);
|
|
2839
|
+
} catch (error) {
|
|
2840
|
+
last_error = error;
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
throw last_error || new Error(`widget resource not found: ${context.plugin_name}/${resource}`);
|
|
2844
|
+
};
|
|
2845
|
+
func.runtime.widgets.get_definition = async function (context) {
|
|
2846
|
+
return await func.runtime.widgets.get_resource(context, 'index.mjs');
|
|
2623
2847
|
};
|
|
2624
2848
|
func.runtime.widgets.get_methods = async function (context) {
|
|
2625
|
-
const index = await func.runtime.widgets.
|
|
2849
|
+
const index = await func.runtime.widgets.get_definition(context);
|
|
2626
2850
|
return index?.methods || {};
|
|
2627
2851
|
};
|
|
2628
2852
|
func.runtime.widgets.load_runtime_css = async function (context) {
|
|
@@ -2633,7 +2857,7 @@ func.runtime.widgets.load_runtime_css = async function (context) {
|
|
|
2633
2857
|
func.utils.load_css_on_demand(plugin_runtime_css_url);
|
|
2634
2858
|
return true;
|
|
2635
2859
|
};
|
|
2636
|
-
func.runtime.widgets.build_params = function (context,
|
|
2860
|
+
func.runtime.widgets.build_params = function (context, container_node, container_data, plugin_setup, api_utils, extra = {}) {
|
|
2637
2861
|
return {
|
|
2638
2862
|
SESSION_ID: context.SESSION_ID,
|
|
2639
2863
|
method: context.method,
|
|
@@ -2642,14 +2866,28 @@ func.runtime.widgets.build_params = function (context, $containerP, plugin_setup
|
|
|
2642
2866
|
sourceP: context.sourceP,
|
|
2643
2867
|
propsP: context.propsP,
|
|
2644
2868
|
plugin_name: context.plugin_name,
|
|
2645
|
-
|
|
2869
|
+
container_node,
|
|
2870
|
+
container_data,
|
|
2646
2871
|
plugin_setup,
|
|
2647
2872
|
report_error: function (descP, warn) {
|
|
2648
2873
|
return func.runtime.widgets.report_error(context, descP, warn);
|
|
2649
2874
|
},
|
|
2875
|
+
log_error: function (descP, warn) {
|
|
2876
|
+
return func.runtime.widgets.report_error(context, descP, warn);
|
|
2877
|
+
},
|
|
2650
2878
|
call_plugin_api: async function (plugin_nameP, dataP) {
|
|
2651
2879
|
return await func.utils.call_plugin_api(context.SESSION_ID, plugin_nameP, dataP);
|
|
2652
2880
|
},
|
|
2881
|
+
set_SYS_GLOBAL_OBJ_WIDGET_INFO: async function (docP) {
|
|
2882
|
+
return await func.utils.set_SYS_GLOBAL_OBJ_WIDGET_INFO(context.SESSION_ID, docP);
|
|
2883
|
+
},
|
|
2884
|
+
run_widgetCallbackEvent: async function () {
|
|
2885
|
+
const event_id = context.propsP?.widgetCallbackEvent;
|
|
2886
|
+
if (!event_id || !api_utils?.invoke_event) {
|
|
2887
|
+
return false;
|
|
2888
|
+
}
|
|
2889
|
+
return await api_utils.invoke_event(event_id);
|
|
2890
|
+
},
|
|
2653
2891
|
api_utils,
|
|
2654
2892
|
...extra,
|
|
2655
2893
|
};
|
|
@@ -3720,25 +3958,722 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
|
|
|
3720
3958
|
// // so slicing is a reliable way to get a fixed length.
|
|
3721
3959
|
// const shortHash = base36Hash.slice(0, 10);
|
|
3722
3960
|
|
|
3723
|
-
// // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
|
|
3724
|
-
// // This ensures the output is always exactly 10 characters long.
|
|
3725
|
-
// return shortHash.padStart(10, '0');
|
|
3726
|
-
// };
|
|
3961
|
+
// // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
|
|
3962
|
+
// // This ensures the output is always exactly 10 characters long.
|
|
3963
|
+
// return shortHash.padStart(10, '0');
|
|
3964
|
+
// };
|
|
3965
|
+
|
|
3966
|
+
func.common.fastHash = function (inputString) {
|
|
3967
|
+
let hash = 0x811c9dc5; // FNV offset basis
|
|
3968
|
+
|
|
3969
|
+
for (let i = 0; i < inputString.length; i++) {
|
|
3970
|
+
hash ^= inputString.charCodeAt(i);
|
|
3971
|
+
// FNV prime multiplication with 32-bit overflow
|
|
3972
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
// Convert to base36 and pad to 10 characters
|
|
3976
|
+
return ((hash >>> 0).toString(36) + '0000000000').slice(0, 10);
|
|
3977
|
+
};
|
|
3978
|
+
|
|
3979
|
+
glb.new_xu_render = false;
|
|
3980
|
+
func.runtime = func.runtime || {};
|
|
3981
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
3982
|
+
func.runtime.render = func.runtime.render || {};
|
|
3983
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
3984
|
+
|
|
3985
|
+
// Shared render-tree contract helpers live here so browser and headless runtimes can resolve the same UI structure.
|
|
3986
|
+
|
|
3987
|
+
func.runtime.render.TREE_CONTRACT_VERSION = func.runtime.render.TREE_CONTRACT_VERSION || 'xuda.render_tree.v1';
|
|
3988
|
+
func.runtime.render._tree_widget_capability_cache = func.runtime.render._tree_widget_capability_cache || {};
|
|
3989
|
+
|
|
3990
|
+
func.runtime.render.safe_clone_tree_value = function (value) {
|
|
3991
|
+
if (typeof structuredClone === 'function') {
|
|
3992
|
+
try {
|
|
3993
|
+
return structuredClone(value);
|
|
3994
|
+
} catch (_) {
|
|
3995
|
+
// Fall through to the recursive clone below.
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3999
|
+
if (Array.isArray(value)) {
|
|
4000
|
+
return value.map(function (item) {
|
|
4001
|
+
return func.runtime.render.safe_clone_tree_value(item);
|
|
4002
|
+
});
|
|
4003
|
+
}
|
|
4004
|
+
|
|
4005
|
+
if (value && typeof value === 'object') {
|
|
4006
|
+
const cloned = {};
|
|
4007
|
+
const keys = Object.keys(value);
|
|
4008
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4009
|
+
const key = keys[index];
|
|
4010
|
+
cloned[key] = func.runtime.render.safe_clone_tree_value(value[key]);
|
|
4011
|
+
}
|
|
4012
|
+
return cloned;
|
|
4013
|
+
}
|
|
4014
|
+
|
|
4015
|
+
return value;
|
|
4016
|
+
};
|
|
4017
|
+
func.runtime.render.sort_tree_debug_value = function (value) {
|
|
4018
|
+
if (Array.isArray(value)) {
|
|
4019
|
+
return value.map(function (item) {
|
|
4020
|
+
return func.runtime.render.sort_tree_debug_value(item);
|
|
4021
|
+
});
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
if (value && typeof value === 'object') {
|
|
4025
|
+
const sorted = {};
|
|
4026
|
+
const keys = Object.keys(value).sort();
|
|
4027
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4028
|
+
const key = keys[index];
|
|
4029
|
+
sorted[key] = func.runtime.render.sort_tree_debug_value(value[key]);
|
|
4030
|
+
}
|
|
4031
|
+
return sorted;
|
|
4032
|
+
}
|
|
4033
|
+
|
|
4034
|
+
return value;
|
|
4035
|
+
};
|
|
4036
|
+
func.runtime.render.is_tree_node = function (nodeP) {
|
|
4037
|
+
return !!nodeP?.contract && nodeP.contract === func.runtime.render.TREE_CONTRACT_VERSION;
|
|
4038
|
+
};
|
|
4039
|
+
func.runtime.render.get_tree_source_node = function (nodeP) {
|
|
4040
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
4041
|
+
return nodeP || null;
|
|
4042
|
+
}
|
|
4043
|
+
return nodeP?.meta?.source_node || null;
|
|
4044
|
+
};
|
|
4045
|
+
func.runtime.render.get_tree_source_snapshot = function (nodeP) {
|
|
4046
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
4047
|
+
return func.runtime.render.safe_clone_tree_value(nodeP);
|
|
4048
|
+
}
|
|
4049
|
+
return nodeP?.meta?.source_snapshot || null;
|
|
4050
|
+
};
|
|
4051
|
+
func.runtime.render.get_tree_node_kind = function (nodeP) {
|
|
4052
|
+
const tag_name = typeof nodeP?.tagName === 'string' ? nodeP.tagName.toLowerCase() : '';
|
|
4053
|
+
const node_type = typeof nodeP?.type === 'string' ? nodeP.type.toLowerCase() : '';
|
|
4054
|
+
|
|
4055
|
+
if (tag_name === 'xu-widget') return 'widget';
|
|
4056
|
+
if (tag_name === 'xu-single-view') return 'single_view';
|
|
4057
|
+
if (tag_name === 'xu-multi-view') return 'multi_view';
|
|
4058
|
+
if (tag_name === 'xu-panel') return 'panel';
|
|
4059
|
+
if (tag_name === 'xu-teleport') return 'teleport';
|
|
4060
|
+
if (tag_name === 'xurender') return 'placeholder';
|
|
4061
|
+
if (tag_name === '#text' || node_type === 'text') return 'text';
|
|
4062
|
+
if (!tag_name && typeof nodeP?.content === 'string' && !Array.isArray(nodeP?.children)) return 'text';
|
|
4063
|
+
return 'element';
|
|
4064
|
+
};
|
|
4065
|
+
func.runtime.render.get_tree_node_id = function (nodeP, pathP) {
|
|
4066
|
+
if (nodeP?.id) {
|
|
4067
|
+
return nodeP.id;
|
|
4068
|
+
}
|
|
4069
|
+
if (nodeP?.id_org) {
|
|
4070
|
+
return nodeP.id_org;
|
|
4071
|
+
}
|
|
4072
|
+
const normalized_path = Array.isArray(pathP) && pathP.length ? pathP.join('.') : 'root';
|
|
4073
|
+
return `tree-node-${normalized_path}`;
|
|
4074
|
+
};
|
|
4075
|
+
func.runtime.render.get_tree_controls = function (attributes) {
|
|
4076
|
+
const attrs = attributes || {};
|
|
4077
|
+
const get_first_defined = function (keys) {
|
|
4078
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4079
|
+
const key = keys[index];
|
|
4080
|
+
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
|
|
4081
|
+
return attrs[key];
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
return null;
|
|
4085
|
+
};
|
|
4086
|
+
return {
|
|
4087
|
+
xu_for: get_first_defined(['xu-for', 'xu-exp:xu-for']),
|
|
4088
|
+
xu_if: get_first_defined(['xu-if', 'xu-exp:xu-if']),
|
|
4089
|
+
xu_render: get_first_defined(['xu-render', 'xu-exp:xu-render']),
|
|
4090
|
+
};
|
|
4091
|
+
};
|
|
4092
|
+
func.runtime.render.get_tree_node_capabilities = async function (options) {
|
|
4093
|
+
const attributes = options?.attributes || {};
|
|
4094
|
+
const plugin_name = attributes['xu-widget'];
|
|
4095
|
+
if (!plugin_name) {
|
|
4096
|
+
return null;
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
const cache = func.runtime.render._tree_widget_capability_cache;
|
|
4100
|
+
if (cache[plugin_name]) {
|
|
4101
|
+
return func.runtime.render.safe_clone_tree_value(cache[plugin_name]);
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
let capabilities = {
|
|
4105
|
+
browser: true,
|
|
4106
|
+
headless: false,
|
|
4107
|
+
};
|
|
4108
|
+
|
|
4109
|
+
try {
|
|
4110
|
+
if (options.SESSION_ID && options.paramsP && func.runtime.widgets?.create_context && func.runtime.widgets?.get_definition) {
|
|
4111
|
+
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, attributes);
|
|
4112
|
+
const definition = await func.runtime.widgets.get_definition(widget_context);
|
|
4113
|
+
capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
4114
|
+
}
|
|
4115
|
+
} catch (_) {
|
|
4116
|
+
// Keep the safe browser-only default when the widget definition is unavailable.
|
|
4117
|
+
}
|
|
4118
|
+
|
|
4119
|
+
cache[plugin_name] = capabilities;
|
|
4120
|
+
return func.runtime.render.safe_clone_tree_value(capabilities);
|
|
4121
|
+
};
|
|
4122
|
+
func.runtime.render.ensure_tree_node = async function (options) {
|
|
4123
|
+
if (!options?.nodeP) {
|
|
4124
|
+
return null;
|
|
4125
|
+
}
|
|
4126
|
+
if (func.runtime.render.is_tree_node(options.nodeP)) {
|
|
4127
|
+
return options.nodeP;
|
|
4128
|
+
}
|
|
4129
|
+
return await func.runtime.render.build_tree(options);
|
|
4130
|
+
};
|
|
4131
|
+
func.runtime.render.build_tree = async function (options) {
|
|
4132
|
+
if (Array.isArray(options?.nodeP)) {
|
|
4133
|
+
return await func.runtime.render.build_tree_list({
|
|
4134
|
+
...options,
|
|
4135
|
+
nodesP: options.nodeP,
|
|
4136
|
+
});
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4139
|
+
const nodeP = options?.nodeP;
|
|
4140
|
+
if (!nodeP) {
|
|
4141
|
+
return null;
|
|
4142
|
+
}
|
|
4143
|
+
if (func.runtime.render.is_tree_node(nodeP)) {
|
|
4144
|
+
return nodeP;
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4147
|
+
const pathP = Array.isArray(options?.pathP) ? options.pathP.slice() : [];
|
|
4148
|
+
const tree_path = pathP.length ? pathP.slice() : [0];
|
|
4149
|
+
const attributes = func.runtime.render.safe_clone_tree_value(nodeP.attributes || {});
|
|
4150
|
+
if (typeof nodeP.content !== 'undefined' && typeof attributes['xu-content'] === 'undefined') {
|
|
4151
|
+
attributes['xu-content'] = func.runtime.render.safe_clone_tree_value(nodeP.content);
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
const widget_capabilities = await func.runtime.render.get_tree_node_capabilities({
|
|
4155
|
+
SESSION_ID: options?.SESSION_ID,
|
|
4156
|
+
paramsP: options?.paramsP,
|
|
4157
|
+
attributes,
|
|
4158
|
+
});
|
|
4159
|
+
const children = [];
|
|
4160
|
+
const child_nodes = Array.isArray(nodeP.children) ? nodeP.children : [];
|
|
4161
|
+
const parent_tree_id = tree_path.join('.');
|
|
4162
|
+
|
|
4163
|
+
for (let index = 0; index < child_nodes.length; index++) {
|
|
4164
|
+
const child_tree = await func.runtime.render.build_tree({
|
|
4165
|
+
...options,
|
|
4166
|
+
nodeP: child_nodes[index],
|
|
4167
|
+
pathP: tree_path.concat(index),
|
|
4168
|
+
parent_tree_id: parent_tree_id,
|
|
4169
|
+
keyP: index,
|
|
4170
|
+
parent_nodeP: nodeP,
|
|
4171
|
+
});
|
|
4172
|
+
if (child_tree) {
|
|
4173
|
+
children.push(child_tree);
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4177
|
+
const tree = {
|
|
4178
|
+
contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
4179
|
+
id: func.runtime.render.get_tree_node_id(nodeP, tree_path),
|
|
4180
|
+
xu_tree_id: `tree.${tree_path.join('.')}`,
|
|
4181
|
+
kind: func.runtime.render.get_tree_node_kind(nodeP),
|
|
4182
|
+
tagName: nodeP.tagName || null,
|
|
4183
|
+
attributes,
|
|
4184
|
+
text: typeof nodeP.text !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.text) : null,
|
|
4185
|
+
content: typeof nodeP.content !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.content) : null,
|
|
4186
|
+
children,
|
|
4187
|
+
meta: {
|
|
4188
|
+
tree_id: tree_path.join('.'),
|
|
4189
|
+
path: tree_path,
|
|
4190
|
+
parent_tree_id: options?.parent_tree_id || null,
|
|
4191
|
+
key: typeof options?.keyP === 'undefined' ? null : options.keyP,
|
|
4192
|
+
recordid: nodeP?.recordid || null,
|
|
4193
|
+
dependency_fields: func.runtime.render.safe_clone_tree_value(nodeP?.dependency_fields || null),
|
|
4194
|
+
iterate_info: func.runtime.render.safe_clone_tree_value(options?.parent_infoP?.iterate_info || nodeP?.iterate_info || null),
|
|
4195
|
+
controls: func.runtime.render.get_tree_controls(attributes),
|
|
4196
|
+
capabilities: widget_capabilities,
|
|
4197
|
+
widget: attributes['xu-widget']
|
|
4198
|
+
? {
|
|
4199
|
+
plugin_name: attributes['xu-widget'],
|
|
4200
|
+
method: attributes['xu-method'] || '_default',
|
|
4201
|
+
capabilities: widget_capabilities,
|
|
4202
|
+
}
|
|
4203
|
+
: null,
|
|
4204
|
+
source_node_id: nodeP?.id || nodeP?.id_org || null,
|
|
4205
|
+
source_node: nodeP,
|
|
4206
|
+
source_snapshot: func.runtime.ui?.get_node_snapshot
|
|
4207
|
+
? func.runtime.ui.get_node_snapshot(nodeP)
|
|
4208
|
+
: func.runtime.render.safe_clone_tree_value(nodeP),
|
|
4209
|
+
},
|
|
4210
|
+
};
|
|
4211
|
+
|
|
4212
|
+
return tree;
|
|
4213
|
+
};
|
|
4214
|
+
func.runtime.render.build_tree_list = async function (options) {
|
|
4215
|
+
const nodes = Array.isArray(options?.nodesP) ? options.nodesP : [];
|
|
4216
|
+
const trees = [];
|
|
4217
|
+
|
|
4218
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
4219
|
+
const tree = await func.runtime.render.build_tree({
|
|
4220
|
+
...options,
|
|
4221
|
+
nodeP: nodes[index],
|
|
4222
|
+
pathP: Array.isArray(options?.pathP) && options.pathP.length ? options.pathP.concat(index) : [index],
|
|
4223
|
+
keyP: index,
|
|
4224
|
+
});
|
|
4225
|
+
if (tree) {
|
|
4226
|
+
trees.push(tree);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
return trees;
|
|
4231
|
+
};
|
|
4232
|
+
func.runtime.render.sanitize_tree_for_debug = function (treeP) {
|
|
4233
|
+
if (Array.isArray(treeP)) {
|
|
4234
|
+
return treeP.map(function (child) {
|
|
4235
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
4236
|
+
});
|
|
4237
|
+
}
|
|
4238
|
+
|
|
4239
|
+
if (!func.runtime.render.is_tree_node(treeP)) {
|
|
4240
|
+
return func.runtime.render.sort_tree_debug_value(func.runtime.render.safe_clone_tree_value(treeP));
|
|
4241
|
+
}
|
|
4242
|
+
|
|
4243
|
+
return {
|
|
4244
|
+
contract: treeP.contract,
|
|
4245
|
+
id: treeP.id,
|
|
4246
|
+
xu_tree_id: treeP.xu_tree_id || null,
|
|
4247
|
+
kind: treeP.kind,
|
|
4248
|
+
tagName: treeP.tagName,
|
|
4249
|
+
attributes: func.runtime.render.sort_tree_debug_value(treeP.attributes || {}),
|
|
4250
|
+
text: treeP.text,
|
|
4251
|
+
content: treeP.content,
|
|
4252
|
+
children: treeP.children.map(function (child) {
|
|
4253
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
4254
|
+
}),
|
|
4255
|
+
meta: {
|
|
4256
|
+
tree_id: treeP.meta?.tree_id || null,
|
|
4257
|
+
path: func.runtime.render.safe_clone_tree_value(treeP.meta?.path || []),
|
|
4258
|
+
parent_tree_id: treeP.meta?.parent_tree_id || null,
|
|
4259
|
+
key: typeof treeP.meta?.key === 'undefined' ? null : treeP.meta.key,
|
|
4260
|
+
recordid: treeP.meta?.recordid || null,
|
|
4261
|
+
dependency_fields: func.runtime.render.sort_tree_debug_value(treeP.meta?.dependency_fields || null),
|
|
4262
|
+
iterate_info: func.runtime.render.sort_tree_debug_value(treeP.meta?.iterate_info || null),
|
|
4263
|
+
controls: func.runtime.render.sort_tree_debug_value(treeP.meta?.controls || null),
|
|
4264
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta?.capabilities || null),
|
|
4265
|
+
widget: treeP.meta?.widget
|
|
4266
|
+
? {
|
|
4267
|
+
plugin_name: treeP.meta.widget.plugin_name,
|
|
4268
|
+
method: treeP.meta.widget.method,
|
|
4269
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta.widget.capabilities || null),
|
|
4270
|
+
}
|
|
4271
|
+
: null,
|
|
4272
|
+
source_node_id: treeP.meta?.source_node_id || null,
|
|
4273
|
+
},
|
|
4274
|
+
};
|
|
4275
|
+
};
|
|
4276
|
+
func.runtime.render.serialize_tree = function (treeP, spacing = 2) {
|
|
4277
|
+
return JSON.stringify(func.runtime.render.sanitize_tree_for_debug(treeP), null, spacing);
|
|
4278
|
+
};
|
|
4279
|
+
func.runtime = func.runtime || {};
|
|
4280
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
4281
|
+
func.runtime.render = func.runtime.render || {};
|
|
4282
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
4283
|
+
|
|
4284
|
+
// Shared string-renderer helpers live here so headless/server runtimes can materialize the render tree without a DOM.
|
|
4285
|
+
|
|
4286
|
+
func.runtime.render.HTML_VOID_TAGS = func.runtime.render.HTML_VOID_TAGS || {
|
|
4287
|
+
area: true,
|
|
4288
|
+
base: true,
|
|
4289
|
+
br: true,
|
|
4290
|
+
col: true,
|
|
4291
|
+
embed: true,
|
|
4292
|
+
hr: true,
|
|
4293
|
+
img: true,
|
|
4294
|
+
input: true,
|
|
4295
|
+
link: true,
|
|
4296
|
+
meta: true,
|
|
4297
|
+
param: true,
|
|
4298
|
+
source: true,
|
|
4299
|
+
track: true,
|
|
4300
|
+
wbr: true,
|
|
4301
|
+
};
|
|
4302
|
+
func.runtime.render.escape_html = function (value) {
|
|
4303
|
+
return `${value ?? ''}`
|
|
4304
|
+
.replaceAll('&', '&')
|
|
4305
|
+
.replaceAll('<', '<')
|
|
4306
|
+
.replaceAll('>', '>')
|
|
4307
|
+
.replaceAll('"', '"')
|
|
4308
|
+
.replaceAll("'", ''');
|
|
4309
|
+
};
|
|
4310
|
+
func.runtime.render.escape_html_attribute = function (value) {
|
|
4311
|
+
return func.runtime.render.escape_html(value);
|
|
4312
|
+
};
|
|
4313
|
+
func.runtime.render.is_html_void_tag = function (tag_name) {
|
|
4314
|
+
return !!func.runtime.render.HTML_VOID_TAGS[(tag_name || '').toLowerCase()];
|
|
4315
|
+
};
|
|
4316
|
+
func.runtime.render.is_falsey_render_value = function (value) {
|
|
4317
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
4318
|
+
return true;
|
|
4319
|
+
}
|
|
4320
|
+
if (typeof value === 'number') {
|
|
4321
|
+
return value === 0;
|
|
4322
|
+
}
|
|
4323
|
+
if (typeof value === 'string') {
|
|
4324
|
+
const normalized = value.trim().toLowerCase();
|
|
4325
|
+
return normalized === '' || normalized === 'false' || normalized === '0' || normalized === 'null' || normalized === 'undefined' || normalized === 'off' || normalized === 'no';
|
|
4326
|
+
}
|
|
4327
|
+
return false;
|
|
4328
|
+
};
|
|
4329
|
+
func.runtime.render.should_render_tree_node = function (treeP) {
|
|
4330
|
+
const controls = treeP?.meta?.controls || {};
|
|
4331
|
+
if (controls.xu_if !== null && controls.xu_if !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_if)) {
|
|
4332
|
+
return false;
|
|
4333
|
+
}
|
|
4334
|
+
if (controls.xu_render !== null && controls.xu_render !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_render)) {
|
|
4335
|
+
return false;
|
|
4336
|
+
}
|
|
4337
|
+
return true;
|
|
4338
|
+
};
|
|
4339
|
+
func.runtime.render.is_tree_control_attribute = function (key) {
|
|
4340
|
+
if (!key) {
|
|
4341
|
+
return false;
|
|
4342
|
+
}
|
|
4343
|
+
return (
|
|
4344
|
+
key.startsWith('xu-exp:') ||
|
|
4345
|
+
key === 'xu-widget' ||
|
|
4346
|
+
key === 'xu-method' ||
|
|
4347
|
+
key === 'xu-for' ||
|
|
4348
|
+
key === 'xu-for-key' ||
|
|
4349
|
+
key === 'xu-for-val' ||
|
|
4350
|
+
key === 'xu-if' ||
|
|
4351
|
+
key === 'xu-render' ||
|
|
4352
|
+
key === 'xu-bind' ||
|
|
4353
|
+
key === 'xu-content' ||
|
|
4354
|
+
key === 'xu-text' ||
|
|
4355
|
+
key === 'xu-html' ||
|
|
4356
|
+
key === 'xu-show' ||
|
|
4357
|
+
key === 'xu-panel-program' ||
|
|
4358
|
+
key === 'xu-teleport'
|
|
4359
|
+
);
|
|
4360
|
+
};
|
|
4361
|
+
func.runtime.render.get_string_renderer_tag_name = function (treeP) {
|
|
4362
|
+
switch (treeP?.kind) {
|
|
4363
|
+
case 'widget':
|
|
4364
|
+
case 'single_view':
|
|
4365
|
+
case 'multi_view':
|
|
4366
|
+
case 'panel':
|
|
4367
|
+
case 'teleport':
|
|
4368
|
+
return 'div';
|
|
4369
|
+
case 'placeholder':
|
|
4370
|
+
return null;
|
|
4371
|
+
case 'text':
|
|
4372
|
+
return null;
|
|
4373
|
+
default:
|
|
4374
|
+
return treeP?.tagName || 'div';
|
|
4375
|
+
}
|
|
4376
|
+
};
|
|
4377
|
+
func.runtime.render.get_tree_terminal_content = function (treeP) {
|
|
4378
|
+
const attributes = treeP?.attributes || {};
|
|
4379
|
+
if (typeof attributes['xu-html'] !== 'undefined' && attributes['xu-html'] !== null) {
|
|
4380
|
+
return {
|
|
4381
|
+
value: `${attributes['xu-html']}`,
|
|
4382
|
+
mode: 'html',
|
|
4383
|
+
};
|
|
4384
|
+
}
|
|
4385
|
+
if (typeof attributes['xu-content'] !== 'undefined' && attributes['xu-content'] !== null) {
|
|
4386
|
+
return {
|
|
4387
|
+
value: `${attributes['xu-content']}`,
|
|
4388
|
+
mode: 'html',
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
4391
|
+
if (typeof attributes['xu-text'] !== 'undefined' && attributes['xu-text'] !== null) {
|
|
4392
|
+
return {
|
|
4393
|
+
value: `${attributes['xu-text']}`,
|
|
4394
|
+
mode: 'text',
|
|
4395
|
+
};
|
|
4396
|
+
}
|
|
4397
|
+
if (treeP?.kind === 'text') {
|
|
4398
|
+
return {
|
|
4399
|
+
value: typeof treeP?.text !== 'undefined' && treeP?.text !== null ? `${treeP.text}` : `${treeP?.content || ''}`,
|
|
4400
|
+
mode: 'text',
|
|
4401
|
+
};
|
|
4402
|
+
}
|
|
4403
|
+
return null;
|
|
4404
|
+
};
|
|
4405
|
+
func.runtime.render.render_tree_terminal_content = function (treeP) {
|
|
4406
|
+
const terminal = func.runtime.render.get_tree_terminal_content(treeP);
|
|
4407
|
+
if (!terminal) {
|
|
4408
|
+
return null;
|
|
4409
|
+
}
|
|
4410
|
+
if (terminal.mode === 'html') {
|
|
4411
|
+
return terminal.value;
|
|
4412
|
+
}
|
|
4413
|
+
return func.runtime.render.escape_html(terminal.value);
|
|
4414
|
+
};
|
|
4415
|
+
func.runtime.render.get_widget_fallback_markup = function (treeP) {
|
|
4416
|
+
const widget_meta = treeP?.meta?.widget || {};
|
|
4417
|
+
const capability_state = widget_meta?.capabilities?.headless ? 'headless-capable' : 'browser-only';
|
|
4418
|
+
return `<!--xuda-widget:${func.runtime.render.escape_html(widget_meta.plugin_name || 'unknown')}:${capability_state}-->`;
|
|
4419
|
+
};
|
|
4420
|
+
func.runtime.render.get_tree_string_attributes = function (treeP, renderer_context) {
|
|
4421
|
+
const attributes = func.runtime.render.safe_clone_tree_value(treeP?.attributes || {});
|
|
4422
|
+
const attr_pairs = [];
|
|
4423
|
+
const keys = Object.keys(attributes);
|
|
4424
|
+
|
|
4425
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4426
|
+
const key = keys[index];
|
|
4427
|
+
if (func.runtime.render.is_tree_control_attribute(key)) {
|
|
4428
|
+
continue;
|
|
4429
|
+
}
|
|
4430
|
+
const value = attributes[key];
|
|
4431
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
4432
|
+
continue;
|
|
4433
|
+
}
|
|
4434
|
+
if (value === true) {
|
|
4435
|
+
attr_pairs.push(key);
|
|
4436
|
+
continue;
|
|
4437
|
+
}
|
|
4438
|
+
const normalized_value = typeof value === 'object' ? JSON.stringify(value) : `${value}`;
|
|
4439
|
+
attr_pairs.push(`${key}="${func.runtime.render.escape_html_attribute(normalized_value)}"`);
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
attr_pairs.push(`data-xuda-kind="${func.runtime.render.escape_html_attribute(treeP?.kind || 'element')}"`);
|
|
4443
|
+
attr_pairs.push(`data-xuda-node-id="${func.runtime.render.escape_html_attribute(treeP?.id || treeP?.meta?.source_node_id || '')}"`);
|
|
4444
|
+
attr_pairs.push(`data-xuda-tree-id="${func.runtime.render.escape_html_attribute(treeP?.meta?.tree_id || '')}"`);
|
|
4445
|
+
|
|
4446
|
+
if (treeP?.kind === 'widget' && treeP?.meta?.widget) {
|
|
4447
|
+
attr_pairs.push(`data-xuda-widget="${func.runtime.render.escape_html_attribute(treeP.meta.widget.plugin_name || '')}"`);
|
|
4448
|
+
attr_pairs.push(`data-xuda-widget-method="${func.runtime.render.escape_html_attribute(treeP.meta.widget.method || '_default')}"`);
|
|
4449
|
+
attr_pairs.push(`data-xuda-widget-capability="${func.runtime.render.escape_html_attribute(treeP.meta.widget.capabilities?.headless ? 'headless' : 'browser')}"`);
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
if (treeP?.kind === 'teleport' && treeP?.attributes?.['xu-teleport']) {
|
|
4453
|
+
attr_pairs.push(`data-xuda-teleport-target="${func.runtime.render.escape_html_attribute(treeP.attributes['xu-teleport'])}"`);
|
|
4454
|
+
}
|
|
4455
|
+
|
|
4456
|
+
if ((treeP?.meta?.controls?.xu_for !== null && treeP?.meta?.controls?.xu_for !== undefined) && !renderer_context?.strip_iteration_markers) {
|
|
4457
|
+
attr_pairs.push('data-xuda-xu-for="pending"');
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
return attr_pairs.length ? ' ' + attr_pairs.join(' ') : '';
|
|
4461
|
+
};
|
|
4462
|
+
func.runtime.render.render_tree_children_to_string = async function (treeP, renderer_context) {
|
|
4463
|
+
if (!Array.isArray(treeP?.children) || !treeP.children.length) {
|
|
4464
|
+
return '';
|
|
4465
|
+
}
|
|
4466
|
+
let html = '';
|
|
4467
|
+
for (let index = 0; index < treeP.children.length; index++) {
|
|
4468
|
+
html += await func.runtime.render.render_tree_to_string(treeP.children[index], {
|
|
4469
|
+
...renderer_context,
|
|
4470
|
+
parent_tree: treeP,
|
|
4471
|
+
});
|
|
4472
|
+
}
|
|
4473
|
+
return html;
|
|
4474
|
+
};
|
|
4475
|
+
func.runtime.render.render_tree_to_string = async function (treeP, renderer_context = {}) {
|
|
4476
|
+
if (!treeP) {
|
|
4477
|
+
return '';
|
|
4478
|
+
}
|
|
4479
|
+
if (Array.isArray(treeP)) {
|
|
4480
|
+
let html = '';
|
|
4481
|
+
for (let index = 0; index < treeP.length; index++) {
|
|
4482
|
+
html += await func.runtime.render.render_tree_to_string(treeP[index], renderer_context);
|
|
4483
|
+
}
|
|
4484
|
+
return html;
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4487
|
+
const ensured_tree = await func.runtime.render.ensure_tree_node({
|
|
4488
|
+
SESSION_ID: renderer_context?.SESSION_ID,
|
|
4489
|
+
nodeP: treeP,
|
|
4490
|
+
paramsP: renderer_context?.paramsP,
|
|
4491
|
+
parent_infoP: renderer_context?.parent_infoP,
|
|
4492
|
+
keyP: renderer_context?.keyP,
|
|
4493
|
+
parent_nodeP: renderer_context?.parent_nodeP,
|
|
4494
|
+
});
|
|
4495
|
+
|
|
4496
|
+
if (!ensured_tree || !func.runtime.render.should_render_tree_node(ensured_tree)) {
|
|
4497
|
+
return '';
|
|
4498
|
+
}
|
|
4499
|
+
|
|
4500
|
+
if (ensured_tree.kind === 'placeholder') {
|
|
4501
|
+
if (renderer_context?.include_placeholders) {
|
|
4502
|
+
return `<!--xuda-placeholder:${func.runtime.render.escape_html(ensured_tree.id || '')}-->`;
|
|
4503
|
+
}
|
|
4504
|
+
return '';
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
if (ensured_tree.kind === 'text') {
|
|
4508
|
+
return func.runtime.render.render_tree_terminal_content(ensured_tree) || '';
|
|
4509
|
+
}
|
|
4510
|
+
|
|
4511
|
+
const tag_name = func.runtime.render.get_string_renderer_tag_name(ensured_tree);
|
|
4512
|
+
if (!tag_name || tag_name.toLowerCase() === 'script') {
|
|
4513
|
+
return '';
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4516
|
+
const attributes = func.runtime.render.get_tree_string_attributes(ensured_tree, renderer_context);
|
|
4517
|
+
const terminal_content = func.runtime.render.render_tree_terminal_content(ensured_tree);
|
|
4518
|
+
let children_html = terminal_content !== null ? terminal_content : await func.runtime.render.render_tree_children_to_string(ensured_tree, renderer_context);
|
|
4519
|
+
|
|
4520
|
+
if (ensured_tree.kind === 'widget' && !children_html) {
|
|
4521
|
+
children_html = func.runtime.render.get_widget_fallback_markup(ensured_tree);
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
if (func.runtime.render.is_html_void_tag(tag_name)) {
|
|
4525
|
+
return `<${tag_name}${attributes}>`;
|
|
4526
|
+
}
|
|
4527
|
+
|
|
4528
|
+
return `<${tag_name}${attributes}>${children_html}</${tag_name}>`;
|
|
4529
|
+
};
|
|
4530
|
+
func.runtime.render.render_to_string = async function (options = {}) {
|
|
4531
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
4532
|
+
SESSION_ID: options.SESSION_ID,
|
|
4533
|
+
nodeP: options.treeP || options.nodeP,
|
|
4534
|
+
paramsP: options.paramsP,
|
|
4535
|
+
parent_infoP: options.parent_infoP,
|
|
4536
|
+
keyP: options.keyP,
|
|
4537
|
+
parent_nodeP: options.parent_nodeP,
|
|
4538
|
+
});
|
|
4539
|
+
|
|
4540
|
+
return await func.runtime.render.render_tree_to_string(treeP, options);
|
|
4541
|
+
};
|
|
4542
|
+
func.runtime.render.get_server_render_mode = function (options = {}) {
|
|
4543
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap({
|
|
4544
|
+
app_computing_mode: options.app_computing_mode,
|
|
4545
|
+
app_render_mode: options.app_render_mode,
|
|
4546
|
+
app_client_activation: options.app_client_activation,
|
|
4547
|
+
});
|
|
4548
|
+
|
|
4549
|
+
return normalized;
|
|
4550
|
+
};
|
|
4551
|
+
func.runtime.render.build_server_render_params = async function (options = {}) {
|
|
4552
|
+
const SESSION_ID = options.SESSION_ID;
|
|
4553
|
+
const prog_id = options.prog_id;
|
|
4554
|
+
const dsSessionP = options.dsSessionP;
|
|
4555
|
+
const _session = SESSION_OBJ?.[SESSION_ID] || {};
|
|
4556
|
+
const _ds = _session?.DS_GLB?.[dsSessionP] || {};
|
|
4557
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
4558
|
+
|
|
4559
|
+
if (!viewDoc?.properties) {
|
|
4560
|
+
throw new Error(`view document not found for ${prog_id}`);
|
|
4561
|
+
}
|
|
4562
|
+
|
|
4563
|
+
const base_params = _ds?.screen_params ? func.runtime.render.safe_clone_tree_value(_ds.screen_params) : {};
|
|
4564
|
+
const screenId = options.screenId || base_params.screenId || `ssr_${prog_id}_${dsSessionP || '0'}`;
|
|
4565
|
+
const paramsP = {
|
|
4566
|
+
...base_params,
|
|
4567
|
+
prog_id,
|
|
4568
|
+
sourceScreenP: null,
|
|
4569
|
+
$callingContainerP: null,
|
|
4570
|
+
triggerIdP: null,
|
|
4571
|
+
callingDataSource_objP: _ds,
|
|
4572
|
+
rowIdP: typeof options.rowIdP !== 'undefined' ? options.rowIdP : (_ds?.currentRecordId || null),
|
|
4573
|
+
renderType: viewDoc.properties?.renderType,
|
|
4574
|
+
parameters_obj_inP: options.parameters_obj_inP || base_params.parameters_obj_inP || options.parameters_raw_obj || {},
|
|
4575
|
+
source_functionP: options.source_functionP || base_params.source_functionP || 'render_string',
|
|
4576
|
+
is_panelP: false,
|
|
4577
|
+
screen_type: options.screen_type || base_params.screen_type || 'render_string',
|
|
4578
|
+
screenInfo: viewDoc,
|
|
4579
|
+
call_screen_propertiesP: base_params.call_screen_propertiesP,
|
|
4580
|
+
parentDataSourceNoP: typeof _ds?.parentDataSourceNo === 'undefined' || _ds?.parentDataSourceNo === null ? 0 : _ds.parentDataSourceNo,
|
|
4581
|
+
parameters_raw_obj: options.parameters_raw_obj || base_params.parameters_raw_obj || {},
|
|
4582
|
+
dsSessionP,
|
|
4583
|
+
screenId,
|
|
4584
|
+
containerIdP: base_params.containerIdP || `ssr_container_${screenId}`,
|
|
4585
|
+
};
|
|
4586
|
+
|
|
4587
|
+
if (_ds) {
|
|
4588
|
+
_ds.screen_params = paramsP;
|
|
4589
|
+
}
|
|
4590
|
+
|
|
4591
|
+
return paramsP;
|
|
4592
|
+
};
|
|
4593
|
+
func.runtime.render.build_prog_tree = async function (options = {}) {
|
|
4594
|
+
const SESSION_ID = options.SESSION_ID;
|
|
4595
|
+
const prog_id = options.prog_id;
|
|
4596
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
4597
|
+
|
|
4598
|
+
if (!viewDoc?.progUi?.length) {
|
|
4599
|
+
throw new Error(`progUi not found for ${prog_id}`);
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
const paramsP = options.paramsP || (await func.runtime.render.build_server_render_params({
|
|
4603
|
+
...options,
|
|
4604
|
+
SESSION_ID,
|
|
4605
|
+
prog_id,
|
|
4606
|
+
viewDoc,
|
|
4607
|
+
}));
|
|
4608
|
+
const root_index = typeof options.root_index === 'number' ? options.root_index : 0;
|
|
4609
|
+
const root_node = func.runtime.render.safe_clone_tree_value(viewDoc.progUi[root_index]);
|
|
4610
|
+
const tree = await func.runtime.render.build_tree({
|
|
4611
|
+
SESSION_ID,
|
|
4612
|
+
nodeP: root_node,
|
|
4613
|
+
paramsP,
|
|
4614
|
+
});
|
|
4615
|
+
|
|
4616
|
+
return {
|
|
4617
|
+
tree,
|
|
4618
|
+
paramsP,
|
|
4619
|
+
viewDoc,
|
|
4620
|
+
};
|
|
4621
|
+
};
|
|
4622
|
+
func.runtime.render.build_ssr_payload = function (render_program, options = {}) {
|
|
4623
|
+
const runtime_profile = func.runtime.render.get_server_render_mode(options);
|
|
4624
|
+
return {
|
|
4625
|
+
contract: 'xuda.ssr.v1',
|
|
4626
|
+
prog_id: options.prog_id,
|
|
4627
|
+
screenId: render_program.paramsP.screenId,
|
|
4628
|
+
containerId: render_program.paramsP.containerIdP,
|
|
4629
|
+
app_computing_mode: runtime_profile.app_computing_mode,
|
|
4630
|
+
app_render_mode: runtime_profile.app_render_mode,
|
|
4631
|
+
app_client_activation: runtime_profile.app_client_activation,
|
|
4632
|
+
tree_contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
4633
|
+
};
|
|
4634
|
+
};
|
|
4635
|
+
func.runtime.render.build_ssr_screen_html = function (html, render_program, options = {}) {
|
|
4636
|
+
const payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
4637
|
+
const screenId = func.runtime.render.escape_html_attribute(payload.screenId || '');
|
|
4638
|
+
const containerId = func.runtime.render.escape_html_attribute(payload.containerId || '');
|
|
4639
|
+
const activation = func.runtime.render.escape_html_attribute(payload.app_client_activation || 'takeover');
|
|
4640
|
+
|
|
4641
|
+
return `<div data-xuda-ssr-embed="true" class="xu_embed_div"><div id="${screenId}" class="xu_embed_container" data-xuda-ssr-screen="true" data-xuda-ssr-screen-id="${screenId}" data-xuda-activation="${activation}" style="display: contents;"><div id="${containerId}" data-xuda-ssr-root-frame="true" data-xuda-ssr-screen-id="${screenId}" data-xuda-activation="${activation}" style="display: contents;">${html}</div></div></div>`;
|
|
4642
|
+
};
|
|
4643
|
+
func.runtime.render.render_prog_to_string = async function (options = {}) {
|
|
4644
|
+
const render_program = await func.runtime.render.build_prog_tree(options);
|
|
4645
|
+
const html = await func.runtime.render.render_to_string({
|
|
4646
|
+
...options,
|
|
4647
|
+
SESSION_ID: options.SESSION_ID,
|
|
4648
|
+
treeP: render_program.tree,
|
|
4649
|
+
paramsP: render_program.paramsP,
|
|
4650
|
+
});
|
|
4651
|
+
const ssr_payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
4652
|
+
const screen_html = func.runtime.render.build_ssr_screen_html(html, render_program, options);
|
|
3727
4653
|
|
|
3728
|
-
|
|
3729
|
-
|
|
4654
|
+
return {
|
|
4655
|
+
prog_id: options.prog_id,
|
|
4656
|
+
dsSessionP: render_program.paramsP.dsSessionP,
|
|
4657
|
+
screenId: render_program.paramsP.screenId,
|
|
4658
|
+
html,
|
|
4659
|
+
screen_html,
|
|
4660
|
+
tree_json: func.runtime.render.serialize_tree(render_program.tree),
|
|
4661
|
+
paramsP: render_program.paramsP,
|
|
4662
|
+
ssr_payload,
|
|
4663
|
+
};
|
|
4664
|
+
};
|
|
4665
|
+
func.runtime = func.runtime || {};
|
|
4666
|
+
func.runtime.platform = func.runtime.platform || {};
|
|
3730
4667
|
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
4668
|
+
func.runtime.platform.dispatch_document_event = function (name, data) {
|
|
4669
|
+
if (typeof document === 'undefined' || typeof CustomEvent === 'undefined') {
|
|
4670
|
+
return false;
|
|
3735
4671
|
}
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
4672
|
+
document.dispatchEvent(new CustomEvent(name, {
|
|
4673
|
+
detail: Array.isArray(data) ? data : [data],
|
|
4674
|
+
}));
|
|
4675
|
+
return true;
|
|
3739
4676
|
};
|
|
3740
|
-
|
|
3741
|
-
glb.new_xu_render = false;
|
|
3742
4677
|
glb.DEBUG_INFO_OBJ = {};
|
|
3743
4678
|
// var CONNECTION_ATTEMPTS = 0;
|
|
3744
4679
|
glb.APP_INFO = {};
|
|
@@ -9116,6 +10051,15 @@ func.runtime.ui.ensure_embed_container = function (SESSION_ID) {
|
|
|
9116
10051
|
const $root_element = func.runtime.ui.get_root_element(SESSION_ID);
|
|
9117
10052
|
let $embed_container = func.runtime.ui.find_by_selector($root_element, `#embed_${SESSION_ID}`, true);
|
|
9118
10053
|
|
|
10054
|
+
if (!$embed_container.length) {
|
|
10055
|
+
const $ssr_embed_container = func.runtime.ui.find_by_selector($root_element, `[data-xuda-ssr-embed="true"]`, true);
|
|
10056
|
+
const ssr_embed_node = func.runtime.ui.get_first_node($ssr_embed_container);
|
|
10057
|
+
if (ssr_embed_node) {
|
|
10058
|
+
ssr_embed_node.id = 'embed_' + SESSION_ID;
|
|
10059
|
+
$embed_container = func.runtime.ui._wrap_matches([ssr_embed_node]);
|
|
10060
|
+
}
|
|
10061
|
+
}
|
|
10062
|
+
|
|
9119
10063
|
if (!$embed_container.length) {
|
|
9120
10064
|
const embed_node = document.createElement('div');
|
|
9121
10065
|
embed_node.id = 'embed_' + SESSION_ID;
|
|
@@ -9151,12 +10095,44 @@ func.runtime.ui.get_root_tag_name = function () {
|
|
|
9151
10095
|
}
|
|
9152
10096
|
return root_tag_name;
|
|
9153
10097
|
};
|
|
10098
|
+
func.runtime.ui.find_ssr_screen_host = function ($container, screenId, containerId) {
|
|
10099
|
+
const container_node = func.runtime.ui.get_first_node($container);
|
|
10100
|
+
if (!container_node || !screenId) {
|
|
10101
|
+
return null;
|
|
10102
|
+
}
|
|
10103
|
+
|
|
10104
|
+
const dialog_node =
|
|
10105
|
+
container_node.querySelector?.(`#${CSS?.escape ? CSS.escape(screenId) : screenId}`) ||
|
|
10106
|
+
container_node.querySelector?.(`[data-xuda-ssr-screen-id="${screenId}"]`);
|
|
10107
|
+
if (!dialog_node) {
|
|
10108
|
+
return null;
|
|
10109
|
+
}
|
|
10110
|
+
|
|
10111
|
+
const root_frame_node =
|
|
10112
|
+
(containerId ? dialog_node.querySelector?.(`#${CSS?.escape ? CSS.escape(containerId) : containerId}`) : null) ||
|
|
10113
|
+
dialog_node.querySelector?.('[data-xuda-ssr-root-frame="true"]');
|
|
10114
|
+
if (!root_frame_node) {
|
|
10115
|
+
return null;
|
|
10116
|
+
}
|
|
10117
|
+
|
|
10118
|
+
return {
|
|
10119
|
+
$dialogDiv: func.runtime.ui._wrap_matches([dialog_node]),
|
|
10120
|
+
$rootFrame: func.runtime.ui._wrap_matches([root_frame_node]),
|
|
10121
|
+
reused_ssr_host: true,
|
|
10122
|
+
};
|
|
10123
|
+
};
|
|
9154
10124
|
func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params, $callingContainerP, screenId) {
|
|
9155
10125
|
var $dialogDiv;
|
|
9156
10126
|
var $rootFrame;
|
|
10127
|
+
let reused_ssr_host = false;
|
|
9157
10128
|
|
|
9158
10129
|
switch (screen_type) {
|
|
9159
10130
|
case 'embed': {
|
|
10131
|
+
const ssr_host = func.runtime.ui.find_ssr_screen_host($callingContainerP, screenId, params?.containerIdP);
|
|
10132
|
+
if (ssr_host) {
|
|
10133
|
+
return ssr_host;
|
|
10134
|
+
}
|
|
10135
|
+
|
|
9160
10136
|
const dialogNode = document.createElement('div');
|
|
9161
10137
|
dialogNode.id = screenId;
|
|
9162
10138
|
dialogNode.setAttribute('ui_engine', UI_FRAMEWORK_INSTALLED);
|
|
@@ -9206,6 +10182,7 @@ func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params,
|
|
|
9206
10182
|
return {
|
|
9207
10183
|
$dialogDiv,
|
|
9208
10184
|
$rootFrame,
|
|
10185
|
+
reused_ssr_host,
|
|
9209
10186
|
};
|
|
9210
10187
|
};
|
|
9211
10188
|
func.runtime.ui.find_xu_ui_in_root = function (SESSION_ID, xu_ui_id) {
|
|
@@ -9239,7 +10216,7 @@ func.runtime.ui.find_element_data_in_root = function (SESSION_ID, dataKey, prope
|
|
|
9239
10216
|
}
|
|
9240
10217
|
return func.runtime.ui.find_in_root(SESSION_ID, '[xu-panel-wrapper-id]');
|
|
9241
10218
|
}
|
|
9242
|
-
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui.
|
|
10219
|
+
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui.get_root_element(SESSION_ID), property, value);
|
|
9243
10220
|
};
|
|
9244
10221
|
func.runtime.ui.find_element_data_in_parent = function ($container, dataKey, property, value) {
|
|
9245
10222
|
const container_node = func.runtime.ui.get_first_node($container);
|
|
@@ -9253,7 +10230,7 @@ func.runtime.ui.find_element_data_in_parent = function ($container, dataKey, pro
|
|
|
9253
10230
|
}
|
|
9254
10231
|
return func.runtime.ui.find_by_selector(parent_node, `[xu-ui-id="${value}"]`);
|
|
9255
10232
|
}
|
|
9256
|
-
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui.
|
|
10233
|
+
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui._wrap_matches([parent_node]), property, value);
|
|
9257
10234
|
};
|
|
9258
10235
|
func.runtime.ui.sync_child_parent_container = function ($div) {
|
|
9259
10236
|
const div_node = func.runtime.ui.get_first_node($div);
|
|
@@ -9360,40 +10337,14 @@ func.runtime.ui.clear_screen_blockers = function () {
|
|
|
9360
10337
|
}
|
|
9361
10338
|
};
|
|
9362
10339
|
|
|
9363
|
-
// @deprecated — no-op shim now that jQuery is removed from the bundle.
|
|
9364
10340
|
func.runtime.ui.as_jquery = function (target) {
|
|
9365
|
-
if (target?.jquery) {
|
|
9366
|
-
return target;
|
|
9367
|
-
}
|
|
9368
10341
|
const node = func.runtime.ui.get_first_node(target);
|
|
9369
|
-
|
|
9370
|
-
const _node_data = {};
|
|
9371
|
-
const _arr = node ? [node] : [];
|
|
9372
|
-
return {
|
|
9373
|
-
0: node,
|
|
9374
|
-
length: _arr.length,
|
|
9375
|
-
toArray: function () { return _arr.slice(); },
|
|
9376
|
-
data: function (key, value) {
|
|
9377
|
-
if (typeof key === 'undefined') return _node_data;
|
|
9378
|
-
if (typeof value !== 'undefined') { _node_data[key] = value; return this; }
|
|
9379
|
-
return _node_data[key];
|
|
9380
|
-
},
|
|
9381
|
-
attr: function (key, value) {
|
|
9382
|
-
if (!node) return undefined;
|
|
9383
|
-
if (typeof value !== 'undefined') { node.setAttribute(key, value); return this; }
|
|
9384
|
-
return node?.getAttribute?.(key);
|
|
9385
|
-
},
|
|
9386
|
-
removeData: function () { for (const k in _node_data) delete _node_data[k]; return this; },
|
|
9387
|
-
children: function () { return { toArray: function () { return node ? Array.from(node.children) : []; } }; },
|
|
9388
|
-
};
|
|
10342
|
+
return func.runtime.ui._wrap_matches(node ? [node] : []);
|
|
9389
10343
|
};
|
|
9390
10344
|
func.runtime.ui.get_first_node = function (target) {
|
|
9391
10345
|
if (!target) {
|
|
9392
10346
|
return null;
|
|
9393
10347
|
}
|
|
9394
|
-
if (target?.jquery) {
|
|
9395
|
-
return target[0] || null;
|
|
9396
|
-
}
|
|
9397
10348
|
if (target?.nodeType) {
|
|
9398
10349
|
return target;
|
|
9399
10350
|
}
|
|
@@ -9411,9 +10362,10 @@ func.runtime.ui.get_data = function (target) {
|
|
|
9411
10362
|
if (meta) return meta;
|
|
9412
10363
|
}
|
|
9413
10364
|
}
|
|
9414
|
-
// fallback: store per-element data on the node itself
|
|
9415
10365
|
if (target_node) {
|
|
9416
|
-
if (!target_node.__xuData)
|
|
10366
|
+
if (!target_node.__xuData) {
|
|
10367
|
+
target_node.__xuData = {};
|
|
10368
|
+
}
|
|
9417
10369
|
return target_node.__xuData;
|
|
9418
10370
|
}
|
|
9419
10371
|
return {};
|
|
@@ -9795,6 +10747,11 @@ func.runtime.ui.build_container_xu_data = function (options) {
|
|
|
9795
10747
|
func.runtime.ui.apply_container_meta = function ($div, options) {
|
|
9796
10748
|
const div_node = func.runtime.ui.get_first_node($div);
|
|
9797
10749
|
func.runtime.ui.set_attr(div_node, 'xu-ui-id', options.ui_id);
|
|
10750
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-kind', options.treeP?.kind || options.nodeP?.tagName || 'element');
|
|
10751
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-node-id', options.nodeP?.id || options.nodeP?.id_org || '');
|
|
10752
|
+
if (options.treeP?.meta?.tree_id !== null && typeof options.treeP?.meta?.tree_id !== 'undefined') {
|
|
10753
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-tree-id', options.treeP.meta.tree_id);
|
|
10754
|
+
}
|
|
9798
10755
|
const xuData = func.runtime.ui.build_container_xu_data(options);
|
|
9799
10756
|
if (options.parent_infoP?.iterate_info) {
|
|
9800
10757
|
xuData.iterate_info = options.parent_infoP.iterate_info;
|
|
@@ -9889,6 +10846,38 @@ func.runtime.ui.create_container_element = function (div_typeP, attr_str, prop,
|
|
|
9889
10846
|
}
|
|
9890
10847
|
return func.runtime.ui.create_element(div, attr_str);
|
|
9891
10848
|
};
|
|
10849
|
+
func.runtime.ui.find_hydration_candidate = function (options) {
|
|
10850
|
+
if (!func.runtime.render.is_hydration_mode(SESSION_OBJ?.[options.SESSION_ID])) {
|
|
10851
|
+
return null;
|
|
10852
|
+
}
|
|
10853
|
+
if (!func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
10854
|
+
return null;
|
|
10855
|
+
}
|
|
10856
|
+
if (options.is_placeholder || !options.treeP?.meta?.tree_id) {
|
|
10857
|
+
return null;
|
|
10858
|
+
}
|
|
10859
|
+
|
|
10860
|
+
const append_node = func.runtime.ui.get_first_node(options.$appendTo || options.$container);
|
|
10861
|
+
if (!append_node) {
|
|
10862
|
+
return null;
|
|
10863
|
+
}
|
|
10864
|
+
|
|
10865
|
+
const children = func.runtime.ui.get_children(append_node);
|
|
10866
|
+
for (let index = 0; index < children.length; index++) {
|
|
10867
|
+
const child = children[index];
|
|
10868
|
+
if (child?.__xuda_hydration_claimed) {
|
|
10869
|
+
continue;
|
|
10870
|
+
}
|
|
10871
|
+
if (func.runtime.ui.get_attr(child, 'data-xuda-tree-id') !== `${options.treeP.meta.tree_id}`) {
|
|
10872
|
+
continue;
|
|
10873
|
+
}
|
|
10874
|
+
child.__xuda_hydration_claimed = true;
|
|
10875
|
+
func.runtime.ui.set_attr(child, 'data-xuda-client-activation', 'hydrate');
|
|
10876
|
+
return child;
|
|
10877
|
+
}
|
|
10878
|
+
|
|
10879
|
+
return null;
|
|
10880
|
+
};
|
|
9892
10881
|
func.runtime.ui.build_xu_ui_id_seed = function (nodeP, dsSessionP, key_path, currentRecordId) {
|
|
9893
10882
|
const nodeId = nodeP.xu_tree_id || nodeP.id;
|
|
9894
10883
|
const elem_key = `${nodeId}-${key_path}-${currentRecordId}`;
|
|
@@ -9941,7 +10930,11 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
9941
10930
|
try {
|
|
9942
10931
|
const key_path = func.runtime.ui.build_container_key_path(container_xu_data, options.keyP, options.parent_infoP, options.nodeP, options.parent_nodeP);
|
|
9943
10932
|
const elem_key = `${options.nodeP.xu_tree_id || options.nodeP.id}-${key_path}-${currentRecordId}`;
|
|
9944
|
-
const
|
|
10933
|
+
const hydration_candidate = func.runtime.ui.find_hydration_candidate({
|
|
10934
|
+
...options,
|
|
10935
|
+
$appendTo,
|
|
10936
|
+
});
|
|
10937
|
+
const $div = hydration_candidate || func.runtime.ui.create_container_element(options.div_typeP, options.attr_str, options.prop, options.nodeP, $appendTo);
|
|
9945
10938
|
const new_ui_id = await func.runtime.ui.generate_xu_ui_id(options.SESSION_ID, options.nodeP, options.$container, options.paramsP, options.keyP, {
|
|
9946
10939
|
container_xu_data,
|
|
9947
10940
|
currentRecordId,
|
|
@@ -9967,9 +10960,10 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
9967
10960
|
parent_infoP: options.parent_infoP,
|
|
9968
10961
|
is_placeholder: options.is_placeholder,
|
|
9969
10962
|
classP: options.classP,
|
|
10963
|
+
treeP: options.treeP,
|
|
9970
10964
|
});
|
|
9971
10965
|
|
|
9972
|
-
if (options.div_typeP !== 'svg') {
|
|
10966
|
+
if (!hydration_candidate && options.div_typeP !== 'svg') {
|
|
9973
10967
|
func.runtime.ui.append_to($div, $appendTo);
|
|
9974
10968
|
}
|
|
9975
10969
|
return $div;
|
|
@@ -12650,9 +13644,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12650
13644
|
|
|
12651
13645
|
const _session = SESSION_OBJ[SESSION_ID];
|
|
12652
13646
|
const screenInfo = structuredClone(screen_ret);
|
|
13647
|
+
const ssr_payload = func.runtime.render.should_use_ssr_payload(SESSION_ID, { prog_id }) ? func.runtime.render.get_ssr_payload(_session) : null;
|
|
12653
13648
|
|
|
12654
13649
|
const screen_type = source_functionP?.split('_')?.[1];
|
|
12655
|
-
const screenId = (glb.screen_num++).toString();
|
|
13650
|
+
const screenId = ssr_payload?.screenId || (glb.screen_num++).toString();
|
|
12656
13651
|
|
|
12657
13652
|
if (SCREEN_BLOCKER_OBJ[prog_id + (sourceScreenP ? '_' + sourceScreenP : '')]) {
|
|
12658
13653
|
const wait_for_SCREEN_BLOCKER_release = function () {
|
|
@@ -12694,6 +13689,8 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12694
13689
|
call_screen_propertiesP,
|
|
12695
13690
|
parentDataSourceNoP: _session.DS_GLB?.[callingDataSource_objP?.dsSession]?.dsSession || callingDataSource_objP?.parentDataSourceNo || 0,
|
|
12696
13691
|
parameters_raw_obj,
|
|
13692
|
+
containerIdP: ssr_payload?.containerId || null,
|
|
13693
|
+
ssr_payload,
|
|
12697
13694
|
};
|
|
12698
13695
|
|
|
12699
13696
|
const screen_host = func.runtime.ui.create_screen_host(SESSION_ID, screen_type, params, $callingContainerP, screenId);
|
|
@@ -12726,6 +13723,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12726
13723
|
func.runtime.ui.set_style($rootFrame, 'display', 'contents');
|
|
12727
13724
|
}
|
|
12728
13725
|
|
|
13726
|
+
if (screen_host.reused_ssr_host && func.runtime.render.is_takeover_mode(_session)) {
|
|
13727
|
+
func.runtime.ui.empty($rootFrame);
|
|
13728
|
+
}
|
|
13729
|
+
|
|
12729
13730
|
if (!is_panelP) func.UI.utils.indicator.screen.busy();
|
|
12730
13731
|
|
|
12731
13732
|
const ret = await func.datasource.create(
|
|
@@ -12767,7 +13768,24 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12767
13768
|
}
|
|
12768
13769
|
let node = structuredClone(viewDoc.progUi);
|
|
12769
13770
|
if (!node.length) return console.warn('ui node empty');
|
|
12770
|
-
const
|
|
13771
|
+
const root_tree = await func.runtime.render.build_tree({
|
|
13772
|
+
SESSION_ID,
|
|
13773
|
+
nodeP: node[0],
|
|
13774
|
+
paramsP: params,
|
|
13775
|
+
});
|
|
13776
|
+
const ret_render_$container = await func.runtime.render.render_tree(root_tree, {
|
|
13777
|
+
SESSION_ID,
|
|
13778
|
+
$container: $rootFrame,
|
|
13779
|
+
parent_infoP: null,
|
|
13780
|
+
paramsP: params,
|
|
13781
|
+
jobNoP,
|
|
13782
|
+
is_skeleton: null,
|
|
13783
|
+
keyP: null,
|
|
13784
|
+
refreshed_ds: null,
|
|
13785
|
+
parent_nodeP: null,
|
|
13786
|
+
check_existP: null,
|
|
13787
|
+
$root_container: $rootFrame,
|
|
13788
|
+
});
|
|
12771
13789
|
|
|
12772
13790
|
if (!is_panelP) func.UI.utils.indicator.screen.normal();
|
|
12773
13791
|
|
|
@@ -12851,7 +13869,7 @@ func.runtime.ui.ensure_nav = function (SESSION_ID, $container) {
|
|
|
12851
13869
|
}
|
|
12852
13870
|
var nav_el = document.createElement('xu-nav');
|
|
12853
13871
|
func.runtime.ui.append($container, nav_el);
|
|
12854
|
-
var $nav = func.runtime.ui.
|
|
13872
|
+
var $nav = func.runtime.ui._wrap_matches([nav_el]);
|
|
12855
13873
|
func.UI.component.init_xu_nav($container, $nav);
|
|
12856
13874
|
return $nav;
|
|
12857
13875
|
};
|
|
@@ -13192,6 +14210,7 @@ func.runtime.ui.render_single_view_node = async function (options) {
|
|
|
13192
14210
|
parent_infoP: options.parent_infoP,
|
|
13193
14211
|
jobNoP: options.jobNoP,
|
|
13194
14212
|
keyP: options.keyP,
|
|
14213
|
+
treeP: options.treeP,
|
|
13195
14214
|
parent_nodeP: options.parent_nodeP,
|
|
13196
14215
|
prop: options.prop,
|
|
13197
14216
|
div_typeP: 'div',
|
|
@@ -13320,6 +14339,7 @@ func.runtime.ui.render_panel_node = async function (options) {
|
|
|
13320
14339
|
parent_infoP: options.parent_infoP,
|
|
13321
14340
|
jobNoP: options.jobNoP,
|
|
13322
14341
|
keyP: options.keyP,
|
|
14342
|
+
treeP: options.treeP,
|
|
13323
14343
|
parent_nodeP: options.parent_nodeP,
|
|
13324
14344
|
prop: options.prop,
|
|
13325
14345
|
$appendToP: $wrapper,
|
|
@@ -13649,6 +14669,14 @@ func.runtime.ui.screen_loading_done = async function (options) {
|
|
|
13649
14669
|
});
|
|
13650
14670
|
|
|
13651
14671
|
const _session = SESSION_OBJ[options.SESSION_ID];
|
|
14672
|
+
if (func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
14673
|
+
const root_node = func.runtime.ui.get_root_node(options.SESSION_ID);
|
|
14674
|
+
if (root_node) {
|
|
14675
|
+
func.runtime.ui.set_attr(root_node, 'data-xuda-client-activation', _session.opt.app_client_activation || 'none');
|
|
14676
|
+
func.runtime.ui.set_attr(root_node, 'data-xuda-ssr-status', _session.opt.app_client_activation === 'hydrate' ? 'hydrated' : 'taken-over');
|
|
14677
|
+
}
|
|
14678
|
+
func.runtime.render.mark_ssr_payload_consumed(options.SESSION_ID);
|
|
14679
|
+
}
|
|
13652
14680
|
func.events.delete_job(options.SESSION_ID, options.jobNoP);
|
|
13653
14681
|
func.UI.utils.screen_blocker(false, options.paramsP.prog_id + (options.paramsP.sourceScreenP ? '_' + options.paramsP.sourceScreenP : ''));
|
|
13654
14682
|
if (_session.prog_id === options.paramsP.prog_id) {
|
|
@@ -13681,7 +14709,7 @@ func.runtime.ui._to_node_array = func.runtime.ui._to_node_array || function (inp
|
|
|
13681
14709
|
if (!input) {
|
|
13682
14710
|
return [];
|
|
13683
14711
|
}
|
|
13684
|
-
if (input
|
|
14712
|
+
if (typeof input?.toArray === 'function' && typeof input?.length === 'number' && !input?.nodeType) {
|
|
13685
14713
|
return input.toArray();
|
|
13686
14714
|
}
|
|
13687
14715
|
if (Array.isArray(input)) {
|
|
@@ -15491,6 +16519,9 @@ func.runtime.render.get_screen_context = function (SESSION_ID, $container, param
|
|
|
15491
16519
|
};
|
|
15492
16520
|
func.runtime.render.get_node_attributes = function (nodeP) {
|
|
15493
16521
|
try {
|
|
16522
|
+
if (func.runtime.render.is_tree_node?.(nodeP)) {
|
|
16523
|
+
return nodeP.attributes;
|
|
16524
|
+
}
|
|
15494
16525
|
return nodeP?.attributes;
|
|
15495
16526
|
} catch (error) {
|
|
15496
16527
|
return undefined;
|
|
@@ -15608,6 +16639,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15608
16639
|
parent_infoP: options.parent_infoP,
|
|
15609
16640
|
jobNoP: options.jobNoP,
|
|
15610
16641
|
keyP: options.keyP,
|
|
16642
|
+
treeP: options.treeP,
|
|
15611
16643
|
parent_nodeP: options.parent_nodeP,
|
|
15612
16644
|
prop: options.prop,
|
|
15613
16645
|
div_typeP: options.element,
|
|
@@ -15630,6 +16662,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15630
16662
|
parent_infoP: options.parent_infoP,
|
|
15631
16663
|
jobNoP: options.jobNoP,
|
|
15632
16664
|
keyP: options.keyP,
|
|
16665
|
+
treeP: options.treeP,
|
|
15633
16666
|
parent_nodeP: options.parent_nodeP,
|
|
15634
16667
|
prop: options.prop,
|
|
15635
16668
|
div_typeP: options.element,
|
|
@@ -16486,18 +17519,28 @@ func.runtime.widgets.render_node = async function (options) {
|
|
|
16486
17519
|
parent_infoP: options.parent_infoP,
|
|
16487
17520
|
jobNoP: options.jobNoP,
|
|
16488
17521
|
keyP: options.keyP,
|
|
17522
|
+
treeP: options.treeP,
|
|
16489
17523
|
parent_nodeP: options.parent_nodeP,
|
|
16490
17524
|
prop: options.prop,
|
|
16491
17525
|
classP: 'widget_wrapper',
|
|
16492
17526
|
});
|
|
16493
17527
|
|
|
17528
|
+
if (func.runtime.render.is_hydration_mode(SESSION_OBJ?.[options.SESSION_ID]) && func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
17529
|
+
func.runtime.ui.empty($div);
|
|
17530
|
+
}
|
|
17531
|
+
|
|
16494
17532
|
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, options.prop);
|
|
16495
17533
|
const { plugin_name, method, propsP, plugin: _plugin } = widget_context;
|
|
16496
17534
|
const report_error = function (descP, warn) {
|
|
16497
17535
|
return func.runtime.widgets.report_error(widget_context, descP, warn);
|
|
16498
17536
|
};
|
|
16499
17537
|
|
|
16500
|
-
const
|
|
17538
|
+
const definition = await func.runtime.widgets.get_definition(widget_context);
|
|
17539
|
+
if (!func.runtime.widgets.supports_current_environment(definition)) {
|
|
17540
|
+
return report_error(`plugin ${plugin_name} is not available in the current environment`, true);
|
|
17541
|
+
}
|
|
17542
|
+
|
|
17543
|
+
const methods = definition?.methods || {};
|
|
16501
17544
|
if (methods && !methods[method]) {
|
|
16502
17545
|
return report_error('method not found');
|
|
16503
17546
|
}
|
|
@@ -16558,7 +17601,13 @@ func.runtime.widgets.render_node = async function (options) {
|
|
|
16558
17601
|
job_id: options.jobNoP,
|
|
16559
17602
|
});
|
|
16560
17603
|
|
|
16561
|
-
const params = func.runtime.widgets.build_params(
|
|
17604
|
+
const params = func.runtime.widgets.build_params(
|
|
17605
|
+
widget_context,
|
|
17606
|
+
func.runtime.ui.get_first_node($div),
|
|
17607
|
+
func.runtime.ui.get_data($div),
|
|
17608
|
+
plugin_setup_ret.data,
|
|
17609
|
+
api_utils,
|
|
17610
|
+
);
|
|
16562
17611
|
const fx = await func.runtime.widgets.get_resource(widget_context, 'runtime.mjs');
|
|
16563
17612
|
|
|
16564
17613
|
await func.runtime.widgets.load_runtime_css(widget_context);
|
|
@@ -16582,9 +17631,306 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16582
17631
|
|
|
16583
17632
|
// Browser-only special node renderers live here so the core render tree can stay focused.
|
|
16584
17633
|
|
|
17634
|
+
const normalize_runtime_tag_name = function (tag_name) {
|
|
17635
|
+
return `${tag_name || ''}`.trim().toLowerCase();
|
|
17636
|
+
};
|
|
17637
|
+
|
|
17638
|
+
const get_runtime_node_attributes = function (nodeP) {
|
|
17639
|
+
if (!nodeP?.attributes || typeof nodeP.attributes !== 'object') {
|
|
17640
|
+
return {};
|
|
17641
|
+
}
|
|
17642
|
+
|
|
17643
|
+
return nodeP.attributes;
|
|
17644
|
+
};
|
|
17645
|
+
|
|
17646
|
+
const get_runtime_node_content = function (nodeP) {
|
|
17647
|
+
if (typeof nodeP?.content === 'string') {
|
|
17648
|
+
return nodeP.content;
|
|
17649
|
+
}
|
|
17650
|
+
|
|
17651
|
+
if (typeof nodeP?.text === 'string') {
|
|
17652
|
+
return nodeP.text;
|
|
17653
|
+
}
|
|
17654
|
+
|
|
17655
|
+
if (!Array.isArray(nodeP?.children)) {
|
|
17656
|
+
return '';
|
|
17657
|
+
}
|
|
17658
|
+
|
|
17659
|
+
return nodeP.children
|
|
17660
|
+
.map(function (child) {
|
|
17661
|
+
if (typeof child === 'string') {
|
|
17662
|
+
return child;
|
|
17663
|
+
}
|
|
17664
|
+
if (typeof child?.content === 'string') {
|
|
17665
|
+
return child.content;
|
|
17666
|
+
}
|
|
17667
|
+
if (typeof child?.text === 'string') {
|
|
17668
|
+
return child.text;
|
|
17669
|
+
}
|
|
17670
|
+
return '';
|
|
17671
|
+
})
|
|
17672
|
+
.join('');
|
|
17673
|
+
};
|
|
17674
|
+
|
|
17675
|
+
const get_runtime_asset_key = function (options, tag_name) {
|
|
17676
|
+
const source_node = options.treeP || options.nodeP || {};
|
|
17677
|
+
const parts = [
|
|
17678
|
+
'xuda-html-asset',
|
|
17679
|
+
options.paramsP?.prog_id || '',
|
|
17680
|
+
tag_name,
|
|
17681
|
+
source_node.id || source_node.id_org || '',
|
|
17682
|
+
typeof options.keyP === 'undefined' || options.keyP === null ? '' : `${options.keyP}`,
|
|
17683
|
+
].filter(function (part) {
|
|
17684
|
+
return `${part || ''}`.trim() !== '';
|
|
17685
|
+
});
|
|
17686
|
+
|
|
17687
|
+
return parts.join(':');
|
|
17688
|
+
};
|
|
17689
|
+
|
|
17690
|
+
const get_runtime_asset_signature = function (attributes, content) {
|
|
17691
|
+
const normalized_attributes = {};
|
|
17692
|
+
const attr_keys = Object.keys(attributes || {}).sort();
|
|
17693
|
+
|
|
17694
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
17695
|
+
const key = attr_keys[index];
|
|
17696
|
+
normalized_attributes[key] = attributes[key];
|
|
17697
|
+
}
|
|
17698
|
+
|
|
17699
|
+
return JSON.stringify({
|
|
17700
|
+
attributes: normalized_attributes,
|
|
17701
|
+
content: `${content || ''}`,
|
|
17702
|
+
});
|
|
17703
|
+
};
|
|
17704
|
+
|
|
17705
|
+
const escape_runtime_asset_selector_value = function (value) {
|
|
17706
|
+
const win = func.runtime.platform.get_window?.();
|
|
17707
|
+
if (win?.CSS?.escape) {
|
|
17708
|
+
return win.CSS.escape(value);
|
|
17709
|
+
}
|
|
17710
|
+
|
|
17711
|
+
return `${value || ''}`.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
17712
|
+
};
|
|
17713
|
+
|
|
17714
|
+
const find_runtime_head_asset = function (head, tag_name, asset_key) {
|
|
17715
|
+
if (!head?.querySelector || !asset_key) {
|
|
17716
|
+
return null;
|
|
17717
|
+
}
|
|
17718
|
+
|
|
17719
|
+
return head.querySelector(`${tag_name}[data-xuda-asset-key="${escape_runtime_asset_selector_value(asset_key)}"]`);
|
|
17720
|
+
};
|
|
17721
|
+
|
|
17722
|
+
const find_runtime_head_asset_by_attr = function (head, tag_name, attr_name, attr_value) {
|
|
17723
|
+
if (!head?.querySelectorAll || !attr_name || !attr_value) {
|
|
17724
|
+
return null;
|
|
17725
|
+
}
|
|
17726
|
+
|
|
17727
|
+
const candidates = Array.from(head.querySelectorAll(tag_name));
|
|
17728
|
+
return (
|
|
17729
|
+
candidates.find(function (candidate) {
|
|
17730
|
+
return candidate.getAttribute(attr_name) === attr_value || candidate[attr_name] === attr_value;
|
|
17731
|
+
}) || null
|
|
17732
|
+
);
|
|
17733
|
+
};
|
|
17734
|
+
|
|
17735
|
+
const wait_for_runtime_asset_load = function (node) {
|
|
17736
|
+
if (!node?.addEventListener) {
|
|
17737
|
+
return Promise.resolve(node);
|
|
17738
|
+
}
|
|
17739
|
+
|
|
17740
|
+
if (node.getAttribute?.('data-xuda-loaded') === 'true') {
|
|
17741
|
+
return Promise.resolve(node);
|
|
17742
|
+
}
|
|
17743
|
+
|
|
17744
|
+
if (!node.getAttribute?.('data-xuda-asset-key')) {
|
|
17745
|
+
return Promise.resolve(node);
|
|
17746
|
+
}
|
|
17747
|
+
|
|
17748
|
+
const tag_name = normalize_runtime_tag_name(node.tagName);
|
|
17749
|
+
if (tag_name !== 'script' && !(tag_name === 'link' && normalize_runtime_tag_name(node.getAttribute?.('rel')) === 'stylesheet')) {
|
|
17750
|
+
return Promise.resolve(node);
|
|
17751
|
+
}
|
|
17752
|
+
|
|
17753
|
+
return new Promise(function (resolve) {
|
|
17754
|
+
const done = function () {
|
|
17755
|
+
node.setAttribute?.('data-xuda-loaded', 'true');
|
|
17756
|
+
resolve(node);
|
|
17757
|
+
};
|
|
17758
|
+
|
|
17759
|
+
node.addEventListener('load', done, { once: true });
|
|
17760
|
+
node.addEventListener('error', done, { once: true });
|
|
17761
|
+
});
|
|
17762
|
+
};
|
|
17763
|
+
|
|
17764
|
+
const remove_runtime_head_asset = function (node) {
|
|
17765
|
+
if (node?.parentNode?.removeChild) {
|
|
17766
|
+
node.parentNode.removeChild(node);
|
|
17767
|
+
}
|
|
17768
|
+
};
|
|
17769
|
+
|
|
17770
|
+
const apply_runtime_asset_metadata = function (node, asset_key, signature) {
|
|
17771
|
+
if (!node?.setAttribute) {
|
|
17772
|
+
return node;
|
|
17773
|
+
}
|
|
17774
|
+
|
|
17775
|
+
if (asset_key) {
|
|
17776
|
+
node.setAttribute('data-xuda-asset-key', asset_key);
|
|
17777
|
+
}
|
|
17778
|
+
node.setAttribute('data-xuda-asset-signature', signature);
|
|
17779
|
+
return node;
|
|
17780
|
+
};
|
|
17781
|
+
|
|
17782
|
+
const create_runtime_head_element = function (doc, tag_name, attributes, asset_key, signature) {
|
|
17783
|
+
const node = doc.createElement(tag_name);
|
|
17784
|
+
apply_runtime_asset_metadata(node, asset_key, signature);
|
|
17785
|
+
func.runtime.platform.apply_element_attributes(node, attributes);
|
|
17786
|
+
return node;
|
|
17787
|
+
};
|
|
17788
|
+
|
|
17789
|
+
const upsert_runtime_head_element = async function (options) {
|
|
17790
|
+
const doc = func.runtime.platform.get_document?.();
|
|
17791
|
+
const head = doc?.head;
|
|
17792
|
+
const tag_name = normalize_runtime_tag_name(options.tag_name);
|
|
17793
|
+
|
|
17794
|
+
if (!doc?.createElement || !head?.appendChild || !tag_name) {
|
|
17795
|
+
return null;
|
|
17796
|
+
}
|
|
17797
|
+
|
|
17798
|
+
const asset_key = options.asset_key || '';
|
|
17799
|
+
const signature = options.signature || '';
|
|
17800
|
+
const attributes = options.attributes || {};
|
|
17801
|
+
const content = typeof options.content === 'string' ? options.content : '';
|
|
17802
|
+
|
|
17803
|
+
const existing_by_key = find_runtime_head_asset(head, tag_name, asset_key);
|
|
17804
|
+
if (existing_by_key && existing_by_key.getAttribute('data-xuda-asset-signature') === signature) {
|
|
17805
|
+
return options.await_load ? await wait_for_runtime_asset_load(existing_by_key) : existing_by_key;
|
|
17806
|
+
}
|
|
17807
|
+
|
|
17808
|
+
if (existing_by_key) {
|
|
17809
|
+
remove_runtime_head_asset(existing_by_key);
|
|
17810
|
+
}
|
|
17811
|
+
|
|
17812
|
+
if (options.find_existing_attr?.name && options.find_existing_attr?.value) {
|
|
17813
|
+
const existing_by_attr = find_runtime_head_asset_by_attr(head, tag_name, options.find_existing_attr.name, options.find_existing_attr.value);
|
|
17814
|
+
if (existing_by_attr) {
|
|
17815
|
+
apply_runtime_asset_metadata(existing_by_attr, asset_key, signature);
|
|
17816
|
+
existing_by_attr.setAttribute?.('data-xuda-loaded', 'true');
|
|
17817
|
+
return existing_by_attr;
|
|
17818
|
+
}
|
|
17819
|
+
}
|
|
17820
|
+
|
|
17821
|
+
const node = create_runtime_head_element(doc, tag_name, attributes, asset_key, signature);
|
|
17822
|
+
|
|
17823
|
+
if (tag_name === 'script' && attributes.src && !Object.prototype.hasOwnProperty.call(attributes, 'async')) {
|
|
17824
|
+
const script_type = normalize_runtime_tag_name(attributes.type);
|
|
17825
|
+
if (script_type !== 'module') {
|
|
17826
|
+
node.async = false;
|
|
17827
|
+
}
|
|
17828
|
+
}
|
|
17829
|
+
|
|
17830
|
+
if (tag_name === 'style' || (tag_name === 'script' && !attributes.src)) {
|
|
17831
|
+
node.textContent = content;
|
|
17832
|
+
}
|
|
17833
|
+
|
|
17834
|
+
head.appendChild(node);
|
|
17835
|
+
|
|
17836
|
+
if (tag_name !== 'script' && tag_name !== 'link') {
|
|
17837
|
+
node.setAttribute('data-xuda-loaded', 'true');
|
|
17838
|
+
}
|
|
17839
|
+
|
|
17840
|
+
return options.await_load ? await wait_for_runtime_asset_load(node) : node;
|
|
17841
|
+
};
|
|
17842
|
+
|
|
17843
|
+
const render_runtime_html_asset = async function (options) {
|
|
17844
|
+
if (options.is_skeleton) {
|
|
17845
|
+
return options.$container;
|
|
17846
|
+
}
|
|
17847
|
+
|
|
17848
|
+
const nodeP = options.treeP || options.nodeP || {};
|
|
17849
|
+
const tag_name = normalize_runtime_tag_name(nodeP.tagName);
|
|
17850
|
+
const attributes = { ...get_runtime_node_attributes(nodeP) };
|
|
17851
|
+
const content = get_runtime_node_content(nodeP);
|
|
17852
|
+
const asset_key = get_runtime_asset_key(options, tag_name);
|
|
17853
|
+
const signature = get_runtime_asset_signature(attributes, content);
|
|
17854
|
+
|
|
17855
|
+
switch (tag_name) {
|
|
17856
|
+
case 'title':
|
|
17857
|
+
func.runtime.platform.set_title(content);
|
|
17858
|
+
return options.$container;
|
|
17859
|
+
case 'style':
|
|
17860
|
+
await upsert_runtime_head_element({
|
|
17861
|
+
tag_name,
|
|
17862
|
+
attributes,
|
|
17863
|
+
content,
|
|
17864
|
+
asset_key,
|
|
17865
|
+
signature,
|
|
17866
|
+
});
|
|
17867
|
+
return options.$container;
|
|
17868
|
+
case 'meta':
|
|
17869
|
+
if (!Object.keys(attributes).length) {
|
|
17870
|
+
return options.$container;
|
|
17871
|
+
}
|
|
17872
|
+
await upsert_runtime_head_element({
|
|
17873
|
+
tag_name,
|
|
17874
|
+
attributes,
|
|
17875
|
+
asset_key,
|
|
17876
|
+
signature,
|
|
17877
|
+
});
|
|
17878
|
+
return options.$container;
|
|
17879
|
+
case 'link': {
|
|
17880
|
+
const href = `${attributes.href || ''}`.trim();
|
|
17881
|
+
if (!href) {
|
|
17882
|
+
return options.$container;
|
|
17883
|
+
}
|
|
17884
|
+
await upsert_runtime_head_element({
|
|
17885
|
+
tag_name,
|
|
17886
|
+
attributes,
|
|
17887
|
+
asset_key,
|
|
17888
|
+
signature,
|
|
17889
|
+
find_existing_attr: {
|
|
17890
|
+
name: 'href',
|
|
17891
|
+
value: href,
|
|
17892
|
+
},
|
|
17893
|
+
await_load: normalize_runtime_tag_name(attributes.rel) === 'stylesheet',
|
|
17894
|
+
});
|
|
17895
|
+
return options.$container;
|
|
17896
|
+
}
|
|
17897
|
+
case 'script': {
|
|
17898
|
+
const src = `${attributes.src || ''}`.trim();
|
|
17899
|
+
if (!src && !content.trim()) {
|
|
17900
|
+
return options.$container;
|
|
17901
|
+
}
|
|
17902
|
+
await upsert_runtime_head_element({
|
|
17903
|
+
tag_name,
|
|
17904
|
+
attributes,
|
|
17905
|
+
content,
|
|
17906
|
+
asset_key,
|
|
17907
|
+
signature,
|
|
17908
|
+
find_existing_attr: src
|
|
17909
|
+
? {
|
|
17910
|
+
name: 'src',
|
|
17911
|
+
value: src,
|
|
17912
|
+
}
|
|
17913
|
+
: null,
|
|
17914
|
+
await_load: !!src,
|
|
17915
|
+
});
|
|
17916
|
+
return options.$container;
|
|
17917
|
+
}
|
|
17918
|
+
default:
|
|
17919
|
+
return null;
|
|
17920
|
+
}
|
|
17921
|
+
};
|
|
17922
|
+
|
|
16585
17923
|
func.runtime.render.render_special_node = async function (options) {
|
|
16586
|
-
|
|
16587
|
-
|
|
17924
|
+
const treeP = options.treeP || null;
|
|
17925
|
+
const nodeP = options.nodeP || func.runtime.render.get_tree_source_node(treeP);
|
|
17926
|
+
const render_tag_name = treeP?.tagName || nodeP?.tagName;
|
|
17927
|
+
const normalized_render_tag_name = normalize_runtime_tag_name(render_tag_name);
|
|
17928
|
+
const is_native_html_asset = ['title', 'style', 'meta', 'link', 'script'].includes(normalized_render_tag_name);
|
|
17929
|
+
|
|
17930
|
+
if (!is_native_html_asset && treeP?.content && nodeP?.attributes) {
|
|
17931
|
+
nodeP.attributes['xu-content'] = treeP.content;
|
|
17932
|
+
} else if (!is_native_html_asset && nodeP?.content && nodeP.attributes) {
|
|
17933
|
+
nodeP.attributes['xu-content'] = nodeP.content;
|
|
16588
17934
|
}
|
|
16589
17935
|
|
|
16590
17936
|
const renderers = {
|
|
@@ -16594,6 +17940,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16594
17940
|
SESSION_ID: options.SESSION_ID,
|
|
16595
17941
|
$container: options.$container,
|
|
16596
17942
|
$root_container: options.$root_container,
|
|
17943
|
+
treeP,
|
|
16597
17944
|
nodeP: options.nodeP,
|
|
16598
17945
|
parent_infoP: options.parent_infoP,
|
|
16599
17946
|
paramsP: options.paramsP,
|
|
@@ -16610,6 +17957,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16610
17957
|
SESSION_ID: options.SESSION_ID,
|
|
16611
17958
|
$container: options.$container,
|
|
16612
17959
|
$root_container: options.$root_container,
|
|
17960
|
+
treeP,
|
|
16613
17961
|
nodeP: options.nodeP,
|
|
16614
17962
|
parent_infoP: options.parent_infoP,
|
|
16615
17963
|
paramsP: options.paramsP,
|
|
@@ -16629,6 +17977,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16629
17977
|
SESSION_ID: options.SESSION_ID,
|
|
16630
17978
|
$container: options.$container,
|
|
16631
17979
|
$root_container: options.$root_container,
|
|
17980
|
+
treeP,
|
|
16632
17981
|
nodeP: options.nodeP,
|
|
16633
17982
|
parent_infoP: options.parent_infoP,
|
|
16634
17983
|
paramsP: options.paramsP,
|
|
@@ -16645,6 +17994,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16645
17994
|
SESSION_ID: options.SESSION_ID,
|
|
16646
17995
|
$container: options.$container,
|
|
16647
17996
|
$root_container: options.$root_container,
|
|
17997
|
+
treeP,
|
|
16648
17998
|
nodeP: options.nodeP,
|
|
16649
17999
|
parent_infoP: options.parent_infoP,
|
|
16650
18000
|
paramsP: options.paramsP,
|
|
@@ -16656,9 +18006,24 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16656
18006
|
refreshed_ds: options.refreshed_ds,
|
|
16657
18007
|
});
|
|
16658
18008
|
},
|
|
18009
|
+
title: async function () {
|
|
18010
|
+
return await render_runtime_html_asset(options);
|
|
18011
|
+
},
|
|
18012
|
+
style: async function () {
|
|
18013
|
+
return await render_runtime_html_asset(options);
|
|
18014
|
+
},
|
|
18015
|
+
meta: async function () {
|
|
18016
|
+
return await render_runtime_html_asset(options);
|
|
18017
|
+
},
|
|
18018
|
+
link: async function () {
|
|
18019
|
+
return await render_runtime_html_asset(options);
|
|
18020
|
+
},
|
|
18021
|
+
script: async function () {
|
|
18022
|
+
return await render_runtime_html_asset(options);
|
|
18023
|
+
},
|
|
16659
18024
|
};
|
|
16660
18025
|
|
|
16661
|
-
const renderer = renderers[
|
|
18026
|
+
const renderer = renderers[normalized_render_tag_name];
|
|
16662
18027
|
if (!renderer) {
|
|
16663
18028
|
return { handled: false };
|
|
16664
18029
|
}
|
|
@@ -16772,8 +18137,9 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16772
18137
|
// Browser-only render tree entrypoints live here so draw/cache helpers can stay focused.
|
|
16773
18138
|
|
|
16774
18139
|
func.runtime.render.create_tree_runtime = function (options) {
|
|
18140
|
+
const render_node = options.nodeP || func.runtime.render.get_tree_source_node(options.treeP);
|
|
16775
18141
|
const render_context = func.runtime.render.get_screen_context(options.SESSION_ID, options.$container, options.paramsP, options.is_skeleton);
|
|
16776
|
-
const prop = func.runtime.render.get_node_attributes(options.
|
|
18142
|
+
const prop = func.runtime.render.get_node_attributes(options.treeP || render_node);
|
|
16777
18143
|
const is_mobile = render_context.is_mobile ? true : false;
|
|
16778
18144
|
const hover_handlers = func.runtime.render.create_hover_handlers({
|
|
16779
18145
|
SESSION_ID: options.SESSION_ID,
|
|
@@ -16788,13 +18154,22 @@ func.runtime.render.create_tree_runtime = function (options) {
|
|
|
16788
18154
|
return await func.runtime.ui.close_modal_session(options.SESSION_ID, modal_id);
|
|
16789
18155
|
};
|
|
16790
18156
|
const iterate_child = async function ($divP, nodeP, parent_infoP, $root_container, before_record_function) {
|
|
18157
|
+
const child_tree = await func.runtime.render.ensure_tree_node({
|
|
18158
|
+
SESSION_ID: options.SESSION_ID,
|
|
18159
|
+
nodeP: nodeP || options.treeP || render_node,
|
|
18160
|
+
parent_infoP,
|
|
18161
|
+
paramsP: options.paramsP,
|
|
18162
|
+
keyP: options.keyP,
|
|
18163
|
+
parent_nodeP: render_node,
|
|
18164
|
+
pathP: options.treeP?.meta?.path || [],
|
|
18165
|
+
});
|
|
16791
18166
|
return await func.runtime.render.iterate_children({
|
|
16792
18167
|
$divP,
|
|
16793
|
-
nodeP,
|
|
18168
|
+
nodeP: child_tree,
|
|
16794
18169
|
is_mobile,
|
|
16795
18170
|
before_record_function,
|
|
16796
18171
|
render_child: async function (key, child) {
|
|
16797
|
-
await options.render_child($divP, child, parent_infoP, key,
|
|
18172
|
+
await options.render_child($divP, child, parent_infoP, key, render_node, $root_container);
|
|
16798
18173
|
},
|
|
16799
18174
|
});
|
|
16800
18175
|
};
|
|
@@ -16824,7 +18199,7 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16824
18199
|
check_existP: options.check_existP,
|
|
16825
18200
|
$root_container: options.$root_container,
|
|
16826
18201
|
prop: options.prop,
|
|
16827
|
-
element: options.nodeP.tagName,
|
|
18202
|
+
element: options.treeP?.tagName || options.nodeP.tagName,
|
|
16828
18203
|
hover_handlers: options.hover_handlers,
|
|
16829
18204
|
include_hover_click: options.include_hover_click,
|
|
16830
18205
|
iterate_child: options.iterate_child,
|
|
@@ -16847,21 +18222,33 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16847
18222
|
nodeP: options.nodeP,
|
|
16848
18223
|
});
|
|
16849
18224
|
};
|
|
16850
|
-
func.runtime.render.
|
|
16851
|
-
if (!
|
|
16852
|
-
const
|
|
16853
|
-
func.runtime?.perf?.
|
|
18225
|
+
func.runtime.render.render_tree = async function (treeP, renderer_context) {
|
|
18226
|
+
if (!treeP) return;
|
|
18227
|
+
const nodeP = func.runtime.render.get_tree_source_node(treeP);
|
|
18228
|
+
const perf_end = func.runtime?.perf?.start?.(renderer_context.SESSION_ID, 'render_ui_tree');
|
|
18229
|
+
func.runtime?.perf?.increment_map?.(renderer_context.SESSION_ID, 'render_node_counts', treeP.id || nodeP?.id || nodeP?.id_org || treeP.tagName || 'unknown');
|
|
16854
18230
|
try {
|
|
16855
18231
|
const tree_runtime = func.runtime.render.create_tree_runtime({
|
|
16856
|
-
SESSION_ID,
|
|
16857
|
-
$container,
|
|
18232
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18233
|
+
$container: renderer_context.$container,
|
|
18234
|
+
treeP,
|
|
16858
18235
|
nodeP,
|
|
16859
|
-
parent_infoP,
|
|
16860
|
-
paramsP,
|
|
16861
|
-
jobNoP,
|
|
16862
|
-
is_skeleton,
|
|
18236
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18237
|
+
paramsP: renderer_context.paramsP,
|
|
18238
|
+
jobNoP: renderer_context.jobNoP,
|
|
18239
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18240
|
+
keyP: renderer_context.keyP,
|
|
16863
18241
|
render_child: async function ($divP, child, parent_infoP, key, parentNodeP, rootContainerP) {
|
|
16864
|
-
await func.runtime.render.
|
|
18242
|
+
await func.runtime.render.render_tree(child, {
|
|
18243
|
+
...renderer_context,
|
|
18244
|
+
$container: $divP,
|
|
18245
|
+
parent_infoP,
|
|
18246
|
+
keyP: key,
|
|
18247
|
+
refreshed_ds: null,
|
|
18248
|
+
parent_nodeP: parentNodeP,
|
|
18249
|
+
check_existP: null,
|
|
18250
|
+
$root_container: rootContainerP,
|
|
18251
|
+
});
|
|
16865
18252
|
},
|
|
16866
18253
|
});
|
|
16867
18254
|
const render_context = tree_runtime.render_context;
|
|
@@ -16873,23 +18260,24 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16873
18260
|
const iterate_child = tree_runtime.iterate_child;
|
|
16874
18261
|
|
|
16875
18262
|
func.runtime.render.log_tree_debug({
|
|
16876
|
-
SESSION_ID,
|
|
16877
|
-
paramsP,
|
|
18263
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18264
|
+
paramsP: renderer_context.paramsP,
|
|
16878
18265
|
nodeP,
|
|
16879
18266
|
_ds,
|
|
16880
18267
|
});
|
|
16881
18268
|
const special_render = await func.runtime.render.render_special_node({
|
|
16882
|
-
SESSION_ID,
|
|
16883
|
-
$container,
|
|
16884
|
-
$root_container,
|
|
18269
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18270
|
+
$container: renderer_context.$container,
|
|
18271
|
+
$root_container: renderer_context.$root_container,
|
|
18272
|
+
treeP,
|
|
16885
18273
|
nodeP,
|
|
16886
|
-
parent_infoP,
|
|
16887
|
-
paramsP,
|
|
16888
|
-
jobNoP,
|
|
16889
|
-
is_skeleton,
|
|
16890
|
-
keyP,
|
|
16891
|
-
refreshed_ds,
|
|
16892
|
-
parent_nodeP,
|
|
18274
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18275
|
+
paramsP: renderer_context.paramsP,
|
|
18276
|
+
jobNoP: renderer_context.jobNoP,
|
|
18277
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18278
|
+
keyP: renderer_context.keyP,
|
|
18279
|
+
refreshed_ds: renderer_context.refreshed_ds,
|
|
18280
|
+
parent_nodeP: renderer_context.parent_nodeP,
|
|
16893
18281
|
prop,
|
|
16894
18282
|
render_context,
|
|
16895
18283
|
hover_handlers,
|
|
@@ -16897,22 +18285,23 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16897
18285
|
close_modal,
|
|
16898
18286
|
});
|
|
16899
18287
|
if (special_render.handled) {
|
|
16900
|
-
func.runtime?.perf?.increment?.(SESSION_ID, 'render_special_node_hits');
|
|
18288
|
+
func.runtime?.perf?.increment?.(renderer_context.SESSION_ID, 'render_special_node_hits');
|
|
16901
18289
|
return special_render.result;
|
|
16902
18290
|
}
|
|
16903
18291
|
return await func.runtime.render.draw_node({
|
|
16904
|
-
SESSION_ID,
|
|
16905
|
-
$container,
|
|
16906
|
-
$root_container,
|
|
18292
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18293
|
+
$container: renderer_context.$container,
|
|
18294
|
+
$root_container: renderer_context.$root_container,
|
|
18295
|
+
treeP,
|
|
16907
18296
|
nodeP,
|
|
16908
|
-
parent_infoP,
|
|
16909
|
-
paramsP,
|
|
16910
|
-
jobNoP,
|
|
16911
|
-
is_skeleton,
|
|
16912
|
-
keyP,
|
|
16913
|
-
refreshed_ds,
|
|
16914
|
-
parent_nodeP,
|
|
16915
|
-
check_existP,
|
|
18297
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18298
|
+
paramsP: renderer_context.paramsP,
|
|
18299
|
+
jobNoP: renderer_context.jobNoP,
|
|
18300
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18301
|
+
keyP: renderer_context.keyP,
|
|
18302
|
+
refreshed_ds: renderer_context.refreshed_ds,
|
|
18303
|
+
parent_nodeP: renderer_context.parent_nodeP,
|
|
18304
|
+
check_existP: renderer_context.check_existP,
|
|
16916
18305
|
prop,
|
|
16917
18306
|
hover_handlers,
|
|
16918
18307
|
include_hover_click,
|
|
@@ -16921,6 +18310,31 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16921
18310
|
} finally {
|
|
16922
18311
|
perf_end?.();
|
|
16923
18312
|
}
|
|
18313
|
+
};
|
|
18314
|
+
func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nodeP, parent_infoP, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $root_container) {
|
|
18315
|
+
if (!nodeP) return;
|
|
18316
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
18317
|
+
SESSION_ID,
|
|
18318
|
+
nodeP,
|
|
18319
|
+
parent_infoP,
|
|
18320
|
+
paramsP,
|
|
18321
|
+
keyP,
|
|
18322
|
+
parent_nodeP,
|
|
18323
|
+
});
|
|
18324
|
+
|
|
18325
|
+
return await func.runtime.render.render_tree(treeP, {
|
|
18326
|
+
SESSION_ID,
|
|
18327
|
+
$container,
|
|
18328
|
+
parent_infoP,
|
|
18329
|
+
paramsP,
|
|
18330
|
+
jobNoP,
|
|
18331
|
+
is_skeleton,
|
|
18332
|
+
keyP,
|
|
18333
|
+
refreshed_ds,
|
|
18334
|
+
parent_nodeP,
|
|
18335
|
+
check_existP,
|
|
18336
|
+
$root_container,
|
|
18337
|
+
});
|
|
16924
18338
|
};
|
|
16925
18339
|
func.runtime = func.runtime || {};
|
|
16926
18340
|
func.runtime.ui = func.runtime.ui || {};
|
|
@@ -17588,7 +19002,7 @@ func.runtime.render.handle_xu_ref = async function (options) {
|
|
|
17588
19002
|
func.runtime.render.handle_xu_bind = async function (options) {
|
|
17589
19003
|
if (options.is_skeleton) return {};
|
|
17590
19004
|
|
|
17591
|
-
const $elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(options.$elm) :
|
|
19005
|
+
const $elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(options.$elm) : options.$elm;
|
|
17592
19006
|
const elm_data = func.runtime.ui.get_data($elm);
|
|
17593
19007
|
const xuData = elm_data?.xuData;
|
|
17594
19008
|
const bind_expression =
|
|
@@ -18444,6 +19858,7 @@ func.runtime.render.handle_xu_panel_program = async function (options) {
|
|
|
18444
19858
|
parent_infoP: options.parent_infoP,
|
|
18445
19859
|
jobNoP: options.jobNoP,
|
|
18446
19860
|
keyP: options.keyP,
|
|
19861
|
+
treeP: options.treeP,
|
|
18447
19862
|
parent_nodeP: options.parent_nodeP,
|
|
18448
19863
|
prop: options.nodeP.attributes,
|
|
18449
19864
|
$appendToP: $wrapper,
|
|
@@ -22457,6 +23872,12 @@ function xuda(...args) {
|
|
|
22457
23872
|
if (typeof opt !== 'object') {
|
|
22458
23873
|
return console.error('Xuda Error - opt argument is not an object');
|
|
22459
23874
|
}
|
|
23875
|
+
|
|
23876
|
+
if (!opt.ssr_payload && func.runtime.platform.get_window()?.__XUDA_SSR__) {
|
|
23877
|
+
opt.ssr_payload = func.runtime.platform.get_window().__XUDA_SSR__;
|
|
23878
|
+
}
|
|
23879
|
+
func.runtime.render.apply_runtime_bootstrap_defaults(opt);
|
|
23880
|
+
|
|
22460
23881
|
glb.URL_PARAMS = func.common.getJsonFromUrl(platform.get_url_href());
|
|
22461
23882
|
|
|
22462
23883
|
glb.worker_type = 'Worker';
|