@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
package/js/xuda-runtime-slim.js
CHANGED
|
@@ -1493,49 +1493,6 @@ if (typeof IS_DOCKER === 'undefined' || typeof IS_PROCESS_SERVER === 'undefined'
|
|
|
1493
1493
|
var DOCS_OBJ = {};
|
|
1494
1494
|
}
|
|
1495
1495
|
|
|
1496
|
-
// Minimal jQuery shim for plugins that still reference $
|
|
1497
|
-
if (typeof $ === 'undefined' && typeof document !== 'undefined') {
|
|
1498
|
-
var $ = function (selector) {
|
|
1499
|
-
var nodes = typeof selector === 'string'
|
|
1500
|
-
? Array.from(document.querySelectorAll(selector))
|
|
1501
|
-
: selector?.nodeType ? [selector] : (selector?.length ? Array.from(selector) : []);
|
|
1502
|
-
var obj = {
|
|
1503
|
-
0: nodes[0], length: nodes.length,
|
|
1504
|
-
toArray: function () { return nodes.slice(); },
|
|
1505
|
-
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); },
|
|
1506
|
-
each: function (fn) { for (var i = 0; i < nodes.length; i++) { fn.call(nodes[i], i, nodes[i]); } return obj; },
|
|
1507
|
-
on: function (ev, fn) { for (var i = 0; i < nodes.length; i++) nodes[i].addEventListener(ev, fn); return obj; },
|
|
1508
|
-
off: function (ev, fn) { for (var i = 0; i < nodes.length; i++) nodes[i].removeEventListener(ev, fn); return obj; },
|
|
1509
|
-
addClass: function (c) { for (var i = 0; i < nodes.length; i++) nodes[i].classList?.add(c); return obj; },
|
|
1510
|
-
removeClass: function (c) { for (var i = 0; i < nodes.length; i++) nodes[i].classList?.remove(c); return obj; },
|
|
1511
|
-
hasClass: function (c) { return nodes[0]?.classList?.contains(c) || false; },
|
|
1512
|
-
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; },
|
|
1513
|
-
css: function (k, v) { for (var i = 0; i < nodes.length; i++) nodes[i].style[k] = v; return obj; },
|
|
1514
|
-
data: function () { return nodes[0]?.__xuData || (nodes[0] ? (nodes[0].__xuData = {}) : {}); },
|
|
1515
|
-
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; },
|
|
1516
|
-
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; },
|
|
1517
|
-
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; },
|
|
1518
|
-
show: function () { for (var i = 0; i < nodes.length; i++) nodes[i].style.display = ''; return obj; },
|
|
1519
|
-
hide: function () { for (var i = 0; i < nodes.length; i++) nodes[i].style.display = 'none'; return obj; },
|
|
1520
|
-
remove: function () { for (var i = 0; i < nodes.length; i++) nodes[i].remove?.(); return obj; },
|
|
1521
|
-
empty: function () { for (var i = 0; i < nodes.length; i++) nodes[i].innerHTML = ''; return obj; },
|
|
1522
|
-
append: function (c) { var n = c?.nodeType ? c : c?.[0]; if (n && nodes[0]) nodes[0].appendChild(n); return obj; },
|
|
1523
|
-
parent: function () { return $(nodes[0]?.parentElement ? [nodes[0].parentElement] : []); },
|
|
1524
|
-
children: function () { return $(nodes[0] ? Array.from(nodes[0].children) : []); },
|
|
1525
|
-
trigger: function (ev, d) { for (var i = 0; i < nodes.length; i++) nodes[i].dispatchEvent(new CustomEvent(ev, { detail: d })); return obj; },
|
|
1526
|
-
is: function (s) { return nodes[0]?.matches?.(s) || false; },
|
|
1527
|
-
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; },
|
|
1528
|
-
unbind: function () { return obj; },
|
|
1529
|
-
clone: function () { return $(nodes[0]?.cloneNode(true) ? [nodes[0].cloneNode(true)] : []); },
|
|
1530
|
-
};
|
|
1531
|
-
obj[Symbol.iterator] = function () { var i = 0; return { next: function () { return i < nodes.length ? { value: nodes[i++], done: false } : { done: true }; } }; };
|
|
1532
|
-
return obj;
|
|
1533
|
-
};
|
|
1534
|
-
$.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]); }); } };
|
|
1535
|
-
$.cookie = function () { return null; };
|
|
1536
|
-
var jQuery = $;
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
1496
|
var glb = {};
|
|
1540
1497
|
var func = {};
|
|
1541
1498
|
func.UI = {};
|
|
@@ -1609,23 +1566,27 @@ glb.PROTECTED_VARS = ['_NULL', '_THIS', '_FOR_KEY', '_FOR_VAL', '_ROWNO', '_ROWI
|
|
|
1609
1566
|
|
|
1610
1567
|
func.common = {};
|
|
1611
1568
|
func.runtime.platform = {
|
|
1569
|
+
get_global: function (name) {
|
|
1570
|
+
try {
|
|
1571
|
+
if (typeof globalThis === 'undefined') {
|
|
1572
|
+
return null;
|
|
1573
|
+
}
|
|
1574
|
+
return globalThis?.[name] || null;
|
|
1575
|
+
} catch (error) {
|
|
1576
|
+
return null;
|
|
1577
|
+
}
|
|
1578
|
+
},
|
|
1612
1579
|
has_window: function () {
|
|
1613
|
-
return
|
|
1580
|
+
return !!func.runtime.platform.get_window();
|
|
1614
1581
|
},
|
|
1615
1582
|
has_document: function () {
|
|
1616
|
-
return
|
|
1583
|
+
return !!func.runtime.platform.get_document();
|
|
1617
1584
|
},
|
|
1618
1585
|
get_window: function () {
|
|
1619
|
-
|
|
1620
|
-
return window;
|
|
1621
|
-
}
|
|
1622
|
-
return null;
|
|
1586
|
+
return func.runtime.platform.get_global('window');
|
|
1623
1587
|
},
|
|
1624
1588
|
get_document: function () {
|
|
1625
|
-
|
|
1626
|
-
return document;
|
|
1627
|
-
}
|
|
1628
|
-
return null;
|
|
1589
|
+
return func.runtime.platform.get_global('document');
|
|
1629
1590
|
},
|
|
1630
1591
|
get_location: function () {
|
|
1631
1592
|
const win = func.runtime.platform.get_window();
|
|
@@ -1636,27 +1597,23 @@ func.runtime.platform = {
|
|
|
1636
1597
|
if (win?.navigator) {
|
|
1637
1598
|
return win.navigator;
|
|
1638
1599
|
}
|
|
1639
|
-
|
|
1640
|
-
return navigator;
|
|
1641
|
-
}
|
|
1642
|
-
return null;
|
|
1600
|
+
return func.runtime.platform.get_global('navi' + 'gator');
|
|
1643
1601
|
},
|
|
1644
1602
|
is_html_element: function (value) {
|
|
1645
|
-
|
|
1603
|
+
const html_element = func.runtime.platform.get_global('HTML' + 'Element');
|
|
1604
|
+
if (typeof html_element !== 'function') {
|
|
1646
1605
|
return false;
|
|
1647
1606
|
}
|
|
1648
|
-
return value instanceof
|
|
1607
|
+
return value instanceof html_element;
|
|
1649
1608
|
},
|
|
1650
1609
|
get_storage: function (type) {
|
|
1651
1610
|
const win = func.runtime.platform.get_window();
|
|
1611
|
+
const storage_key = type === 'session' ? 'session' + 'Storage' : 'local' + 'Storage';
|
|
1652
1612
|
try {
|
|
1653
1613
|
if (!win) {
|
|
1654
1614
|
return null;
|
|
1655
1615
|
}
|
|
1656
|
-
|
|
1657
|
-
return win.sessionStorage || null;
|
|
1658
|
-
}
|
|
1659
|
-
return win.localStorage || null;
|
|
1616
|
+
return win?.[storage_key] || null;
|
|
1660
1617
|
} catch (error) {
|
|
1661
1618
|
return null;
|
|
1662
1619
|
}
|
|
@@ -1813,9 +1770,8 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
1813
1770
|
handlers[i](data);
|
|
1814
1771
|
}
|
|
1815
1772
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
document.dispatchEvent(new CustomEvent(name, { detail: Array.isArray(data) ? data : [data] }));
|
|
1773
|
+
if (typeof func.runtime.platform.dispatch_document_event === 'function') {
|
|
1774
|
+
func.runtime.platform.dispatch_document_event(name, data);
|
|
1819
1775
|
}
|
|
1820
1776
|
} finally {
|
|
1821
1777
|
func.runtime.platform._emitting[name] = false;
|
|
@@ -1823,35 +1779,111 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
1823
1779
|
};
|
|
1824
1780
|
|
|
1825
1781
|
// ── Platform helpers for DOM-independent resource loading ──
|
|
1826
|
-
func.runtime.platform.
|
|
1827
|
-
if (
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1782
|
+
func.runtime.platform.apply_element_attributes = function (node, attributes, excluded_keys = []) {
|
|
1783
|
+
if (!node?.setAttribute || !attributes) {
|
|
1784
|
+
return node;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
const excluded = new Set(excluded_keys || []);
|
|
1788
|
+
const attr_keys = Object.keys(attributes);
|
|
1789
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
1790
|
+
const key = attr_keys[index];
|
|
1791
|
+
if (!key || excluded.has(key)) {
|
|
1792
|
+
continue;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
const value = attributes[key];
|
|
1796
|
+
if (value === false || typeof value === 'undefined') {
|
|
1797
|
+
continue;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
node.setAttribute(key, value === null ? '' : `${value}`);
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
return node;
|
|
1804
|
+
};
|
|
1805
|
+
func.runtime.platform.load_script = function (url, type, callback, attributes) {
|
|
1806
|
+
const doc = func.runtime.platform.get_document();
|
|
1807
|
+
if (!doc?.createElement || !doc?.head?.appendChild) {
|
|
1808
|
+
if (callback) {
|
|
1809
|
+
callback();
|
|
1810
|
+
}
|
|
1811
|
+
return;
|
|
1835
1812
|
}
|
|
1813
|
+
const find_existing_script = function () {
|
|
1814
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
1815
|
+
const scripts = doc.querySelectorAll ? Array.from(doc.querySelectorAll('script')) : [];
|
|
1816
|
+
return scripts.find(function (script) {
|
|
1817
|
+
if (asset_key && script.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
1818
|
+
return true;
|
|
1819
|
+
}
|
|
1820
|
+
return !!(url && script.getAttribute('src') === url);
|
|
1821
|
+
}) || null;
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1824
|
+
const existing_script = find_existing_script();
|
|
1825
|
+
if (existing_script) {
|
|
1826
|
+
if (callback) {
|
|
1827
|
+
if (existing_script.getAttribute('data-xuda-loaded') === 'true' || !url) {
|
|
1828
|
+
callback();
|
|
1829
|
+
} else {
|
|
1830
|
+
existing_script.addEventListener('load', callback, { once: true });
|
|
1831
|
+
existing_script.addEventListener('error', callback, { once: true });
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
return existing_script;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
const script = doc.createElement('script');
|
|
1838
|
+
script.src = url;
|
|
1839
|
+
if (type) script.type = type;
|
|
1840
|
+
func.runtime.platform.apply_element_attributes(script, attributes, ['src', 'type']);
|
|
1841
|
+
script.onload = function () {
|
|
1842
|
+
script.setAttribute('data-xuda-loaded', 'true');
|
|
1843
|
+
if (callback) {
|
|
1844
|
+
callback();
|
|
1845
|
+
}
|
|
1846
|
+
};
|
|
1847
|
+
script.onerror = function () {
|
|
1848
|
+
if (callback) {
|
|
1849
|
+
callback();
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
doc.head.appendChild(script);
|
|
1853
|
+
return script;
|
|
1836
1854
|
};
|
|
1837
|
-
func.runtime.platform.load_css = function (href) {
|
|
1838
|
-
|
|
1855
|
+
func.runtime.platform.load_css = function (href, attributes) {
|
|
1856
|
+
const doc = func.runtime.platform.get_document();
|
|
1857
|
+
if (!doc?.createElement || !doc?.head) {
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1839
1860
|
try {
|
|
1840
|
-
|
|
1861
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
1862
|
+
const existing_links = doc.querySelectorAll ? Array.from(doc.querySelectorAll('link')) : [];
|
|
1863
|
+
const existing = existing_links.find(function (link) {
|
|
1864
|
+
if (asset_key && link.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
1865
|
+
return true;
|
|
1866
|
+
}
|
|
1867
|
+
return !!(href && link.getAttribute('href') === href);
|
|
1868
|
+
});
|
|
1869
|
+
if (existing) return existing;
|
|
1841
1870
|
} catch (err) {
|
|
1842
1871
|
return;
|
|
1843
1872
|
}
|
|
1844
|
-
const link =
|
|
1873
|
+
const link = doc.createElement('link');
|
|
1845
1874
|
link.rel = 'stylesheet';
|
|
1846
1875
|
link.type = 'text/css';
|
|
1847
1876
|
link.href = href;
|
|
1848
|
-
|
|
1877
|
+
func.runtime.platform.apply_element_attributes(link, attributes, ['href']);
|
|
1878
|
+
doc.head.insertBefore(link, doc.head.firstChild);
|
|
1879
|
+
return link;
|
|
1849
1880
|
};
|
|
1850
1881
|
func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
1851
|
-
|
|
1882
|
+
const doc = func.runtime.platform.get_document();
|
|
1883
|
+
if (!doc?.getElementsByTagName) return;
|
|
1852
1884
|
const tagName = filetype === 'js' ? 'script' : filetype === 'css' ? 'link' : 'none';
|
|
1853
1885
|
const attr = filetype === 'js' ? 'src' : filetype === 'css' ? 'href' : 'none';
|
|
1854
|
-
const elements =
|
|
1886
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
1855
1887
|
for (let i = elements.length - 1; i >= 0; i--) {
|
|
1856
1888
|
if (elements[i] && elements[i].getAttribute(attr) != null && elements[i].getAttribute(attr).indexOf(filename) !== -1) {
|
|
1857
1889
|
elements[i].parentNode.removeChild(elements[i]);
|
|
@@ -1859,15 +1891,17 @@ func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
|
1859
1891
|
}
|
|
1860
1892
|
};
|
|
1861
1893
|
func.runtime.platform.inject_css = function (cssText) {
|
|
1862
|
-
|
|
1863
|
-
|
|
1894
|
+
const doc = func.runtime.platform.get_document();
|
|
1895
|
+
if (!doc?.createElement || !doc?.head?.appendChild || !cssText) return;
|
|
1896
|
+
const style = doc.createElement('style');
|
|
1864
1897
|
style.type = 'text/css';
|
|
1865
1898
|
style.textContent = cssText;
|
|
1866
|
-
|
|
1899
|
+
doc.head.appendChild(style);
|
|
1867
1900
|
};
|
|
1868
1901
|
func.runtime.platform.set_title = function (title) {
|
|
1869
|
-
|
|
1870
|
-
|
|
1902
|
+
const doc = func.runtime.platform.get_document();
|
|
1903
|
+
if (doc) {
|
|
1904
|
+
doc.title = title;
|
|
1871
1905
|
}
|
|
1872
1906
|
};
|
|
1873
1907
|
func.runtime.platform.set_cursor = function (element, cursor) {
|
|
@@ -2133,6 +2167,147 @@ func.runtime.workers.delete_promise = function (SESSION_ID, worker_id, promise_q
|
|
|
2133
2167
|
delete registry_entry.promise_queue[promise_queue_id];
|
|
2134
2168
|
return true;
|
|
2135
2169
|
};
|
|
2170
|
+
func.runtime.render.clone_runtime_options = function (value) {
|
|
2171
|
+
if (typeof structuredClone === 'function') {
|
|
2172
|
+
try {
|
|
2173
|
+
return structuredClone(value);
|
|
2174
|
+
} catch (_) {}
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
if (Array.isArray(value)) {
|
|
2178
|
+
return value.map(function (item) {
|
|
2179
|
+
return func.runtime.render.clone_runtime_options(item);
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
if (value && typeof value === 'object') {
|
|
2184
|
+
const cloned = {};
|
|
2185
|
+
const keys = Object.keys(value);
|
|
2186
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2187
|
+
const key = keys[index];
|
|
2188
|
+
cloned[key] = func.runtime.render.clone_runtime_options(value[key]);
|
|
2189
|
+
}
|
|
2190
|
+
return cloned;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
return value;
|
|
2194
|
+
};
|
|
2195
|
+
func.runtime.render.normalize_runtime_bootstrap = function (raw_options = {}) {
|
|
2196
|
+
const options = raw_options || {};
|
|
2197
|
+
let app_computing_mode = options.app_computing_mode || '';
|
|
2198
|
+
let app_render_mode = options.app_render_mode || '';
|
|
2199
|
+
let app_client_activation = options.app_client_activation || '';
|
|
2200
|
+
let ssr_payload = options.ssr_payload || null;
|
|
2201
|
+
|
|
2202
|
+
if (typeof ssr_payload === 'string') {
|
|
2203
|
+
try {
|
|
2204
|
+
ssr_payload = JSON.parse(ssr_payload);
|
|
2205
|
+
} catch (_) {
|
|
2206
|
+
ssr_payload = null;
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
2211
|
+
ssr_payload = func.runtime.render.clone_runtime_options(ssr_payload);
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
if (!app_computing_mode) {
|
|
2215
|
+
if (app_render_mode === 'ssr_first_page' || app_render_mode === 'ssr_full') {
|
|
2216
|
+
app_computing_mode = 'server';
|
|
2217
|
+
} else {
|
|
2218
|
+
app_computing_mode = 'main';
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
switch (app_computing_mode) {
|
|
2223
|
+
case 'main':
|
|
2224
|
+
app_render_mode = 'csr';
|
|
2225
|
+
app_client_activation = 'none';
|
|
2226
|
+
break;
|
|
2227
|
+
|
|
2228
|
+
case 'worker':
|
|
2229
|
+
app_render_mode = 'csr';
|
|
2230
|
+
app_client_activation = 'none';
|
|
2231
|
+
break;
|
|
2232
|
+
|
|
2233
|
+
default:
|
|
2234
|
+
app_computing_mode = 'server';
|
|
2235
|
+
if (app_render_mode !== 'ssr_full') {
|
|
2236
|
+
app_render_mode = 'ssr_first_page';
|
|
2237
|
+
}
|
|
2238
|
+
app_client_activation = app_render_mode === 'ssr_full' ? 'hydrate' : 'takeover';
|
|
2239
|
+
break;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
2243
|
+
if (!ssr_payload.app_render_mode) {
|
|
2244
|
+
ssr_payload.app_render_mode = app_render_mode;
|
|
2245
|
+
}
|
|
2246
|
+
if (!ssr_payload.app_client_activation) {
|
|
2247
|
+
ssr_payload.app_client_activation = app_client_activation;
|
|
2248
|
+
}
|
|
2249
|
+
if (!ssr_payload.app_computing_mode) {
|
|
2250
|
+
ssr_payload.app_computing_mode = app_computing_mode;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
return {
|
|
2255
|
+
app_computing_mode,
|
|
2256
|
+
app_render_mode,
|
|
2257
|
+
app_client_activation,
|
|
2258
|
+
ssr_payload,
|
|
2259
|
+
};
|
|
2260
|
+
};
|
|
2261
|
+
func.runtime.render.apply_runtime_bootstrap_defaults = function (target = {}) {
|
|
2262
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target);
|
|
2263
|
+
target.app_computing_mode = normalized.app_computing_mode;
|
|
2264
|
+
target.app_render_mode = normalized.app_render_mode;
|
|
2265
|
+
target.app_client_activation = normalized.app_client_activation;
|
|
2266
|
+
target.ssr_payload = normalized.ssr_payload;
|
|
2267
|
+
return normalized;
|
|
2268
|
+
};
|
|
2269
|
+
func.runtime.render.is_server_render_mode = function (target = {}) {
|
|
2270
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2271
|
+
return normalized.app_computing_mode === 'server' && normalized.app_render_mode !== 'csr';
|
|
2272
|
+
};
|
|
2273
|
+
func.runtime.render.is_takeover_mode = function (target = {}) {
|
|
2274
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2275
|
+
return normalized.app_client_activation === 'takeover';
|
|
2276
|
+
};
|
|
2277
|
+
func.runtime.render.is_hydration_mode = function (target = {}) {
|
|
2278
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2279
|
+
return normalized.app_client_activation === 'hydrate';
|
|
2280
|
+
};
|
|
2281
|
+
func.runtime.render.get_ssr_payload = function (target = {}) {
|
|
2282
|
+
if (target?.opt?.ssr_payload) {
|
|
2283
|
+
return target.opt.ssr_payload;
|
|
2284
|
+
}
|
|
2285
|
+
if (target?.ssr_payload) {
|
|
2286
|
+
return target.ssr_payload;
|
|
2287
|
+
}
|
|
2288
|
+
const win = func.runtime.platform.get_window();
|
|
2289
|
+
return win?.__XUDA_SSR__ || null;
|
|
2290
|
+
};
|
|
2291
|
+
func.runtime.render.should_use_ssr_payload = function (SESSION_ID, paramsP) {
|
|
2292
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
2293
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
2294
|
+
if (!payload || payload._consumed) {
|
|
2295
|
+
return false;
|
|
2296
|
+
}
|
|
2297
|
+
if (paramsP?.prog_id && payload.prog_id && payload.prog_id !== paramsP.prog_id) {
|
|
2298
|
+
return false;
|
|
2299
|
+
}
|
|
2300
|
+
return true;
|
|
2301
|
+
};
|
|
2302
|
+
func.runtime.render.mark_ssr_payload_consumed = function (SESSION_ID) {
|
|
2303
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
2304
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
2305
|
+
if (!payload || typeof payload !== 'object') {
|
|
2306
|
+
return false;
|
|
2307
|
+
}
|
|
2308
|
+
payload._consumed = true;
|
|
2309
|
+
return true;
|
|
2310
|
+
};
|
|
2136
2311
|
func.runtime.render.get_root_data_system = function (SESSION_ID) {
|
|
2137
2312
|
return SESSION_OBJ[SESSION_ID]?.DS_GLB?.[0]?.data_system || null;
|
|
2138
2313
|
};
|
|
@@ -2536,10 +2711,10 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
2536
2711
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
2537
2712
|
break;
|
|
2538
2713
|
case 'css':
|
|
2539
|
-
|
|
2714
|
+
func.runtime.platform.load_css(normalized_resource.src);
|
|
2540
2715
|
break;
|
|
2541
2716
|
case 'module':
|
|
2542
|
-
func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2717
|
+
await func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2543
2718
|
break;
|
|
2544
2719
|
default:
|
|
2545
2720
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
@@ -2555,12 +2730,36 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
2555
2730
|
func.runtime.resources.get_plugin_manifest_entry = function (_session, plugin_name) {
|
|
2556
2731
|
return APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name] || null;
|
|
2557
2732
|
};
|
|
2558
|
-
func.runtime.resources.
|
|
2733
|
+
func.runtime.resources.get_plugin_resource_candidates = function (_session, plugin, resource) {
|
|
2559
2734
|
const manifest_entry = plugin?.manifest?.[resource];
|
|
2560
|
-
|
|
2735
|
+
const default_path = `${manifest_entry?.dist ? 'dist/' : ''}${resource}`;
|
|
2736
|
+
const candidates = [];
|
|
2737
|
+
if (_session?.worker_type === 'Dev' && manifest_entry?.dist && /\.mjs$/.test(resource)) {
|
|
2738
|
+
candidates.push(`src/${resource}`);
|
|
2739
|
+
}
|
|
2740
|
+
candidates.push(default_path);
|
|
2741
|
+
return Array.from(new Set(candidates.filter(Boolean)));
|
|
2742
|
+
};
|
|
2743
|
+
func.runtime.resources.get_plugin_module_path = function (plugin, resource, _session) {
|
|
2744
|
+
return func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource)[0] || resource;
|
|
2561
2745
|
};
|
|
2562
2746
|
func.runtime.resources.get_plugin_module_url = async function (SESSION_ID, plugin_name, plugin, resource) {
|
|
2563
|
-
|
|
2747
|
+
const _session = SESSION_OBJ[SESSION_ID];
|
|
2748
|
+
return await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, func.runtime.resources.get_plugin_module_path(plugin, resource, _session));
|
|
2749
|
+
};
|
|
2750
|
+
func.runtime.resources.import_plugin_module = async function (SESSION_ID, plugin_name, plugin, resource) {
|
|
2751
|
+
const _session = SESSION_OBJ[SESSION_ID];
|
|
2752
|
+
const candidates = func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource);
|
|
2753
|
+
let last_error = null;
|
|
2754
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
2755
|
+
const candidate = candidates[index];
|
|
2756
|
+
try {
|
|
2757
|
+
return await func.utils.get_plugin_resource(SESSION_ID, plugin_name, candidate);
|
|
2758
|
+
} catch (error) {
|
|
2759
|
+
last_error = error;
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
throw last_error || new Error(`plugin resource not found: ${plugin_name}/${resource}`);
|
|
2564
2763
|
};
|
|
2565
2764
|
func.runtime.resources.load_plugin_runtime_css = async function (SESSION_ID, plugin_name, plugin) {
|
|
2566
2765
|
if (!plugin?.manifest?.['runtime.mjs']?.dist || !plugin?.manifest?.['runtime.mjs']?.css) {
|
|
@@ -2590,12 +2789,10 @@ func.runtime.resources.run_ui_plugin = async function (SESSION_ID, paramsP, $elm
|
|
|
2590
2789
|
|
|
2591
2790
|
await func.runtime.resources.load_plugin_runtime_css(SESSION_ID, plugin_name, plugin);
|
|
2592
2791
|
|
|
2593
|
-
const
|
|
2594
|
-
const plugin_index_resources = await import(plugin_index_src);
|
|
2792
|
+
const plugin_index_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'index.mjs');
|
|
2595
2793
|
const properties = await func.runtime.resources.resolve_plugin_properties(SESSION_ID, paramsP.dsSessionP, value?.attributes, plugin_index_resources.properties);
|
|
2596
2794
|
|
|
2597
|
-
const
|
|
2598
|
-
const plugin_runtime_resources = await import(plugin_runtime_src);
|
|
2795
|
+
const plugin_runtime_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'runtime.mjs');
|
|
2599
2796
|
|
|
2600
2797
|
if (plugin_runtime_resources.cdn && Array.isArray(plugin_runtime_resources.cdn)) {
|
|
2601
2798
|
for await (const resource of plugin_runtime_resources.cdn) {
|
|
@@ -2678,25 +2875,52 @@ func.runtime.widgets.get_fields_data = async function (context, fields, props) {
|
|
|
2678
2875
|
|
|
2679
2876
|
return { code: return_code, data: data_obj };
|
|
2680
2877
|
};
|
|
2878
|
+
func.runtime.widgets.get_resource_candidates = function (context, resource) {
|
|
2879
|
+
return func.runtime.resources.get_plugin_resource_candidates(context._session, context.plugin, resource);
|
|
2880
|
+
};
|
|
2881
|
+
func.runtime.widgets.normalize_capabilities = function (definition) {
|
|
2882
|
+
const capabilities = definition?.capabilities || {};
|
|
2883
|
+
return {
|
|
2884
|
+
browser: capabilities.browser !== false,
|
|
2885
|
+
headless: capabilities.headless === true,
|
|
2886
|
+
};
|
|
2887
|
+
};
|
|
2888
|
+
func.runtime.widgets.supports_current_environment = function (definition) {
|
|
2889
|
+
const capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
2890
|
+
if (func.runtime.platform.has_document()) {
|
|
2891
|
+
return capabilities.browser !== false;
|
|
2892
|
+
}
|
|
2893
|
+
return !!capabilities.headless;
|
|
2894
|
+
};
|
|
2681
2895
|
func.runtime.widgets.get_resource_path = function (context, resource) {
|
|
2896
|
+
const relative_path = func.runtime.widgets.get_resource_candidates(context, resource)[0] || resource;
|
|
2682
2897
|
if (context._session.worker_type === 'Dev') {
|
|
2683
|
-
return `../../plugins/${context.plugin_name}/${
|
|
2898
|
+
return `../../plugins/${context.plugin_name}/${relative_path}`;
|
|
2684
2899
|
}
|
|
2685
|
-
|
|
2686
|
-
const dist_prefix = manifest_entry?.dist ? 'dist/' : '';
|
|
2687
|
-
return `https://${context._session.domain}/plugins/${context.plugin_name}/${dist_prefix}${resource}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
|
|
2900
|
+
return `https://${context._session.domain}/plugins/${context.plugin_name}/${relative_path}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
|
|
2688
2901
|
};
|
|
2689
2902
|
func.runtime.widgets.load_css_style = function (context) {
|
|
2690
2903
|
func.utils.load_css_on_demand(func.runtime.widgets.get_resource_path(context, 'style.css'));
|
|
2691
2904
|
return true;
|
|
2692
2905
|
};
|
|
2693
2906
|
func.runtime.widgets.get_resource = async function (context, resource) {
|
|
2694
|
-
const
|
|
2695
|
-
|
|
2696
|
-
|
|
2907
|
+
const candidates = func.runtime.widgets.get_resource_candidates(context, resource);
|
|
2908
|
+
let last_error = null;
|
|
2909
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
2910
|
+
const candidate = candidates[index];
|
|
2911
|
+
try {
|
|
2912
|
+
return await func.utils.get_plugin_resource(context.SESSION_ID, context.plugin_name, candidate);
|
|
2913
|
+
} catch (error) {
|
|
2914
|
+
last_error = error;
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
throw last_error || new Error(`widget resource not found: ${context.plugin_name}/${resource}`);
|
|
2918
|
+
};
|
|
2919
|
+
func.runtime.widgets.get_definition = async function (context) {
|
|
2920
|
+
return await func.runtime.widgets.get_resource(context, 'index.mjs');
|
|
2697
2921
|
};
|
|
2698
2922
|
func.runtime.widgets.get_methods = async function (context) {
|
|
2699
|
-
const index = await func.runtime.widgets.
|
|
2923
|
+
const index = await func.runtime.widgets.get_definition(context);
|
|
2700
2924
|
return index?.methods || {};
|
|
2701
2925
|
};
|
|
2702
2926
|
func.runtime.widgets.load_runtime_css = async function (context) {
|
|
@@ -2707,7 +2931,7 @@ func.runtime.widgets.load_runtime_css = async function (context) {
|
|
|
2707
2931
|
func.utils.load_css_on_demand(plugin_runtime_css_url);
|
|
2708
2932
|
return true;
|
|
2709
2933
|
};
|
|
2710
|
-
func.runtime.widgets.build_params = function (context,
|
|
2934
|
+
func.runtime.widgets.build_params = function (context, container_node, container_data, plugin_setup, api_utils, extra = {}) {
|
|
2711
2935
|
return {
|
|
2712
2936
|
SESSION_ID: context.SESSION_ID,
|
|
2713
2937
|
method: context.method,
|
|
@@ -2716,14 +2940,28 @@ func.runtime.widgets.build_params = function (context, $containerP, plugin_setup
|
|
|
2716
2940
|
sourceP: context.sourceP,
|
|
2717
2941
|
propsP: context.propsP,
|
|
2718
2942
|
plugin_name: context.plugin_name,
|
|
2719
|
-
|
|
2943
|
+
container_node,
|
|
2944
|
+
container_data,
|
|
2720
2945
|
plugin_setup,
|
|
2721
2946
|
report_error: function (descP, warn) {
|
|
2722
2947
|
return func.runtime.widgets.report_error(context, descP, warn);
|
|
2723
2948
|
},
|
|
2949
|
+
log_error: function (descP, warn) {
|
|
2950
|
+
return func.runtime.widgets.report_error(context, descP, warn);
|
|
2951
|
+
},
|
|
2724
2952
|
call_plugin_api: async function (plugin_nameP, dataP) {
|
|
2725
2953
|
return await func.utils.call_plugin_api(context.SESSION_ID, plugin_nameP, dataP);
|
|
2726
2954
|
},
|
|
2955
|
+
set_SYS_GLOBAL_OBJ_WIDGET_INFO: async function (docP) {
|
|
2956
|
+
return await func.utils.set_SYS_GLOBAL_OBJ_WIDGET_INFO(context.SESSION_ID, docP);
|
|
2957
|
+
},
|
|
2958
|
+
run_widgetCallbackEvent: async function () {
|
|
2959
|
+
const event_id = context.propsP?.widgetCallbackEvent;
|
|
2960
|
+
if (!event_id || !api_utils?.invoke_event) {
|
|
2961
|
+
return false;
|
|
2962
|
+
}
|
|
2963
|
+
return await api_utils.invoke_event(event_id);
|
|
2964
|
+
},
|
|
2727
2965
|
api_utils,
|
|
2728
2966
|
...extra,
|
|
2729
2967
|
};
|
|
@@ -3794,25 +4032,722 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
|
|
|
3794
4032
|
// // so slicing is a reliable way to get a fixed length.
|
|
3795
4033
|
// const shortHash = base36Hash.slice(0, 10);
|
|
3796
4034
|
|
|
3797
|
-
// // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
|
|
3798
|
-
// // This ensures the output is always exactly 10 characters long.
|
|
3799
|
-
// return shortHash.padStart(10, '0');
|
|
3800
|
-
// };
|
|
4035
|
+
// // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
|
|
4036
|
+
// // This ensures the output is always exactly 10 characters long.
|
|
4037
|
+
// return shortHash.padStart(10, '0');
|
|
4038
|
+
// };
|
|
4039
|
+
|
|
4040
|
+
func.common.fastHash = function (inputString) {
|
|
4041
|
+
let hash = 0x811c9dc5; // FNV offset basis
|
|
4042
|
+
|
|
4043
|
+
for (let i = 0; i < inputString.length; i++) {
|
|
4044
|
+
hash ^= inputString.charCodeAt(i);
|
|
4045
|
+
// FNV prime multiplication with 32-bit overflow
|
|
4046
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
4047
|
+
}
|
|
4048
|
+
|
|
4049
|
+
// Convert to base36 and pad to 10 characters
|
|
4050
|
+
return ((hash >>> 0).toString(36) + '0000000000').slice(0, 10);
|
|
4051
|
+
};
|
|
4052
|
+
|
|
4053
|
+
glb.new_xu_render = false;
|
|
4054
|
+
func.runtime = func.runtime || {};
|
|
4055
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
4056
|
+
func.runtime.render = func.runtime.render || {};
|
|
4057
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
4058
|
+
|
|
4059
|
+
// Shared render-tree contract helpers live here so browser and headless runtimes can resolve the same UI structure.
|
|
4060
|
+
|
|
4061
|
+
func.runtime.render.TREE_CONTRACT_VERSION = func.runtime.render.TREE_CONTRACT_VERSION || 'xuda.render_tree.v1';
|
|
4062
|
+
func.runtime.render._tree_widget_capability_cache = func.runtime.render._tree_widget_capability_cache || {};
|
|
4063
|
+
|
|
4064
|
+
func.runtime.render.safe_clone_tree_value = function (value) {
|
|
4065
|
+
if (typeof structuredClone === 'function') {
|
|
4066
|
+
try {
|
|
4067
|
+
return structuredClone(value);
|
|
4068
|
+
} catch (_) {
|
|
4069
|
+
// Fall through to the recursive clone below.
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
|
|
4073
|
+
if (Array.isArray(value)) {
|
|
4074
|
+
return value.map(function (item) {
|
|
4075
|
+
return func.runtime.render.safe_clone_tree_value(item);
|
|
4076
|
+
});
|
|
4077
|
+
}
|
|
4078
|
+
|
|
4079
|
+
if (value && typeof value === 'object') {
|
|
4080
|
+
const cloned = {};
|
|
4081
|
+
const keys = Object.keys(value);
|
|
4082
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4083
|
+
const key = keys[index];
|
|
4084
|
+
cloned[key] = func.runtime.render.safe_clone_tree_value(value[key]);
|
|
4085
|
+
}
|
|
4086
|
+
return cloned;
|
|
4087
|
+
}
|
|
4088
|
+
|
|
4089
|
+
return value;
|
|
4090
|
+
};
|
|
4091
|
+
func.runtime.render.sort_tree_debug_value = function (value) {
|
|
4092
|
+
if (Array.isArray(value)) {
|
|
4093
|
+
return value.map(function (item) {
|
|
4094
|
+
return func.runtime.render.sort_tree_debug_value(item);
|
|
4095
|
+
});
|
|
4096
|
+
}
|
|
4097
|
+
|
|
4098
|
+
if (value && typeof value === 'object') {
|
|
4099
|
+
const sorted = {};
|
|
4100
|
+
const keys = Object.keys(value).sort();
|
|
4101
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4102
|
+
const key = keys[index];
|
|
4103
|
+
sorted[key] = func.runtime.render.sort_tree_debug_value(value[key]);
|
|
4104
|
+
}
|
|
4105
|
+
return sorted;
|
|
4106
|
+
}
|
|
4107
|
+
|
|
4108
|
+
return value;
|
|
4109
|
+
};
|
|
4110
|
+
func.runtime.render.is_tree_node = function (nodeP) {
|
|
4111
|
+
return !!nodeP?.contract && nodeP.contract === func.runtime.render.TREE_CONTRACT_VERSION;
|
|
4112
|
+
};
|
|
4113
|
+
func.runtime.render.get_tree_source_node = function (nodeP) {
|
|
4114
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
4115
|
+
return nodeP || null;
|
|
4116
|
+
}
|
|
4117
|
+
return nodeP?.meta?.source_node || null;
|
|
4118
|
+
};
|
|
4119
|
+
func.runtime.render.get_tree_source_snapshot = function (nodeP) {
|
|
4120
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
4121
|
+
return func.runtime.render.safe_clone_tree_value(nodeP);
|
|
4122
|
+
}
|
|
4123
|
+
return nodeP?.meta?.source_snapshot || null;
|
|
4124
|
+
};
|
|
4125
|
+
func.runtime.render.get_tree_node_kind = function (nodeP) {
|
|
4126
|
+
const tag_name = typeof nodeP?.tagName === 'string' ? nodeP.tagName.toLowerCase() : '';
|
|
4127
|
+
const node_type = typeof nodeP?.type === 'string' ? nodeP.type.toLowerCase() : '';
|
|
4128
|
+
|
|
4129
|
+
if (tag_name === 'xu-widget') return 'widget';
|
|
4130
|
+
if (tag_name === 'xu-single-view') return 'single_view';
|
|
4131
|
+
if (tag_name === 'xu-multi-view') return 'multi_view';
|
|
4132
|
+
if (tag_name === 'xu-panel') return 'panel';
|
|
4133
|
+
if (tag_name === 'xu-teleport') return 'teleport';
|
|
4134
|
+
if (tag_name === 'xurender') return 'placeholder';
|
|
4135
|
+
if (tag_name === '#text' || node_type === 'text') return 'text';
|
|
4136
|
+
if (!tag_name && typeof nodeP?.content === 'string' && !Array.isArray(nodeP?.children)) return 'text';
|
|
4137
|
+
return 'element';
|
|
4138
|
+
};
|
|
4139
|
+
func.runtime.render.get_tree_node_id = function (nodeP, pathP) {
|
|
4140
|
+
if (nodeP?.id) {
|
|
4141
|
+
return nodeP.id;
|
|
4142
|
+
}
|
|
4143
|
+
if (nodeP?.id_org) {
|
|
4144
|
+
return nodeP.id_org;
|
|
4145
|
+
}
|
|
4146
|
+
const normalized_path = Array.isArray(pathP) && pathP.length ? pathP.join('.') : 'root';
|
|
4147
|
+
return `tree-node-${normalized_path}`;
|
|
4148
|
+
};
|
|
4149
|
+
func.runtime.render.get_tree_controls = function (attributes) {
|
|
4150
|
+
const attrs = attributes || {};
|
|
4151
|
+
const get_first_defined = function (keys) {
|
|
4152
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4153
|
+
const key = keys[index];
|
|
4154
|
+
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
|
|
4155
|
+
return attrs[key];
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
return null;
|
|
4159
|
+
};
|
|
4160
|
+
return {
|
|
4161
|
+
xu_for: get_first_defined(['xu-for', 'xu-exp:xu-for']),
|
|
4162
|
+
xu_if: get_first_defined(['xu-if', 'xu-exp:xu-if']),
|
|
4163
|
+
xu_render: get_first_defined(['xu-render', 'xu-exp:xu-render']),
|
|
4164
|
+
};
|
|
4165
|
+
};
|
|
4166
|
+
func.runtime.render.get_tree_node_capabilities = async function (options) {
|
|
4167
|
+
const attributes = options?.attributes || {};
|
|
4168
|
+
const plugin_name = attributes['xu-widget'];
|
|
4169
|
+
if (!plugin_name) {
|
|
4170
|
+
return null;
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
const cache = func.runtime.render._tree_widget_capability_cache;
|
|
4174
|
+
if (cache[plugin_name]) {
|
|
4175
|
+
return func.runtime.render.safe_clone_tree_value(cache[plugin_name]);
|
|
4176
|
+
}
|
|
4177
|
+
|
|
4178
|
+
let capabilities = {
|
|
4179
|
+
browser: true,
|
|
4180
|
+
headless: false,
|
|
4181
|
+
};
|
|
4182
|
+
|
|
4183
|
+
try {
|
|
4184
|
+
if (options.SESSION_ID && options.paramsP && func.runtime.widgets?.create_context && func.runtime.widgets?.get_definition) {
|
|
4185
|
+
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, attributes);
|
|
4186
|
+
const definition = await func.runtime.widgets.get_definition(widget_context);
|
|
4187
|
+
capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
4188
|
+
}
|
|
4189
|
+
} catch (_) {
|
|
4190
|
+
// Keep the safe browser-only default when the widget definition is unavailable.
|
|
4191
|
+
}
|
|
4192
|
+
|
|
4193
|
+
cache[plugin_name] = capabilities;
|
|
4194
|
+
return func.runtime.render.safe_clone_tree_value(capabilities);
|
|
4195
|
+
};
|
|
4196
|
+
func.runtime.render.ensure_tree_node = async function (options) {
|
|
4197
|
+
if (!options?.nodeP) {
|
|
4198
|
+
return null;
|
|
4199
|
+
}
|
|
4200
|
+
if (func.runtime.render.is_tree_node(options.nodeP)) {
|
|
4201
|
+
return options.nodeP;
|
|
4202
|
+
}
|
|
4203
|
+
return await func.runtime.render.build_tree(options);
|
|
4204
|
+
};
|
|
4205
|
+
func.runtime.render.build_tree = async function (options) {
|
|
4206
|
+
if (Array.isArray(options?.nodeP)) {
|
|
4207
|
+
return await func.runtime.render.build_tree_list({
|
|
4208
|
+
...options,
|
|
4209
|
+
nodesP: options.nodeP,
|
|
4210
|
+
});
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
const nodeP = options?.nodeP;
|
|
4214
|
+
if (!nodeP) {
|
|
4215
|
+
return null;
|
|
4216
|
+
}
|
|
4217
|
+
if (func.runtime.render.is_tree_node(nodeP)) {
|
|
4218
|
+
return nodeP;
|
|
4219
|
+
}
|
|
4220
|
+
|
|
4221
|
+
const pathP = Array.isArray(options?.pathP) ? options.pathP.slice() : [];
|
|
4222
|
+
const tree_path = pathP.length ? pathP.slice() : [0];
|
|
4223
|
+
const attributes = func.runtime.render.safe_clone_tree_value(nodeP.attributes || {});
|
|
4224
|
+
if (typeof nodeP.content !== 'undefined' && typeof attributes['xu-content'] === 'undefined') {
|
|
4225
|
+
attributes['xu-content'] = func.runtime.render.safe_clone_tree_value(nodeP.content);
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
const widget_capabilities = await func.runtime.render.get_tree_node_capabilities({
|
|
4229
|
+
SESSION_ID: options?.SESSION_ID,
|
|
4230
|
+
paramsP: options?.paramsP,
|
|
4231
|
+
attributes,
|
|
4232
|
+
});
|
|
4233
|
+
const children = [];
|
|
4234
|
+
const child_nodes = Array.isArray(nodeP.children) ? nodeP.children : [];
|
|
4235
|
+
const parent_tree_id = tree_path.join('.');
|
|
4236
|
+
|
|
4237
|
+
for (let index = 0; index < child_nodes.length; index++) {
|
|
4238
|
+
const child_tree = await func.runtime.render.build_tree({
|
|
4239
|
+
...options,
|
|
4240
|
+
nodeP: child_nodes[index],
|
|
4241
|
+
pathP: tree_path.concat(index),
|
|
4242
|
+
parent_tree_id: parent_tree_id,
|
|
4243
|
+
keyP: index,
|
|
4244
|
+
parent_nodeP: nodeP,
|
|
4245
|
+
});
|
|
4246
|
+
if (child_tree) {
|
|
4247
|
+
children.push(child_tree);
|
|
4248
|
+
}
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
const tree = {
|
|
4252
|
+
contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
4253
|
+
id: func.runtime.render.get_tree_node_id(nodeP, tree_path),
|
|
4254
|
+
xu_tree_id: `tree.${tree_path.join('.')}`,
|
|
4255
|
+
kind: func.runtime.render.get_tree_node_kind(nodeP),
|
|
4256
|
+
tagName: nodeP.tagName || null,
|
|
4257
|
+
attributes,
|
|
4258
|
+
text: typeof nodeP.text !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.text) : null,
|
|
4259
|
+
content: typeof nodeP.content !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.content) : null,
|
|
4260
|
+
children,
|
|
4261
|
+
meta: {
|
|
4262
|
+
tree_id: tree_path.join('.'),
|
|
4263
|
+
path: tree_path,
|
|
4264
|
+
parent_tree_id: options?.parent_tree_id || null,
|
|
4265
|
+
key: typeof options?.keyP === 'undefined' ? null : options.keyP,
|
|
4266
|
+
recordid: nodeP?.recordid || null,
|
|
4267
|
+
dependency_fields: func.runtime.render.safe_clone_tree_value(nodeP?.dependency_fields || null),
|
|
4268
|
+
iterate_info: func.runtime.render.safe_clone_tree_value(options?.parent_infoP?.iterate_info || nodeP?.iterate_info || null),
|
|
4269
|
+
controls: func.runtime.render.get_tree_controls(attributes),
|
|
4270
|
+
capabilities: widget_capabilities,
|
|
4271
|
+
widget: attributes['xu-widget']
|
|
4272
|
+
? {
|
|
4273
|
+
plugin_name: attributes['xu-widget'],
|
|
4274
|
+
method: attributes['xu-method'] || '_default',
|
|
4275
|
+
capabilities: widget_capabilities,
|
|
4276
|
+
}
|
|
4277
|
+
: null,
|
|
4278
|
+
source_node_id: nodeP?.id || nodeP?.id_org || null,
|
|
4279
|
+
source_node: nodeP,
|
|
4280
|
+
source_snapshot: func.runtime.ui?.get_node_snapshot
|
|
4281
|
+
? func.runtime.ui.get_node_snapshot(nodeP)
|
|
4282
|
+
: func.runtime.render.safe_clone_tree_value(nodeP),
|
|
4283
|
+
},
|
|
4284
|
+
};
|
|
4285
|
+
|
|
4286
|
+
return tree;
|
|
4287
|
+
};
|
|
4288
|
+
func.runtime.render.build_tree_list = async function (options) {
|
|
4289
|
+
const nodes = Array.isArray(options?.nodesP) ? options.nodesP : [];
|
|
4290
|
+
const trees = [];
|
|
4291
|
+
|
|
4292
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
4293
|
+
const tree = await func.runtime.render.build_tree({
|
|
4294
|
+
...options,
|
|
4295
|
+
nodeP: nodes[index],
|
|
4296
|
+
pathP: Array.isArray(options?.pathP) && options.pathP.length ? options.pathP.concat(index) : [index],
|
|
4297
|
+
keyP: index,
|
|
4298
|
+
});
|
|
4299
|
+
if (tree) {
|
|
4300
|
+
trees.push(tree);
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
return trees;
|
|
4305
|
+
};
|
|
4306
|
+
func.runtime.render.sanitize_tree_for_debug = function (treeP) {
|
|
4307
|
+
if (Array.isArray(treeP)) {
|
|
4308
|
+
return treeP.map(function (child) {
|
|
4309
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
4310
|
+
});
|
|
4311
|
+
}
|
|
4312
|
+
|
|
4313
|
+
if (!func.runtime.render.is_tree_node(treeP)) {
|
|
4314
|
+
return func.runtime.render.sort_tree_debug_value(func.runtime.render.safe_clone_tree_value(treeP));
|
|
4315
|
+
}
|
|
4316
|
+
|
|
4317
|
+
return {
|
|
4318
|
+
contract: treeP.contract,
|
|
4319
|
+
id: treeP.id,
|
|
4320
|
+
xu_tree_id: treeP.xu_tree_id || null,
|
|
4321
|
+
kind: treeP.kind,
|
|
4322
|
+
tagName: treeP.tagName,
|
|
4323
|
+
attributes: func.runtime.render.sort_tree_debug_value(treeP.attributes || {}),
|
|
4324
|
+
text: treeP.text,
|
|
4325
|
+
content: treeP.content,
|
|
4326
|
+
children: treeP.children.map(function (child) {
|
|
4327
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
4328
|
+
}),
|
|
4329
|
+
meta: {
|
|
4330
|
+
tree_id: treeP.meta?.tree_id || null,
|
|
4331
|
+
path: func.runtime.render.safe_clone_tree_value(treeP.meta?.path || []),
|
|
4332
|
+
parent_tree_id: treeP.meta?.parent_tree_id || null,
|
|
4333
|
+
key: typeof treeP.meta?.key === 'undefined' ? null : treeP.meta.key,
|
|
4334
|
+
recordid: treeP.meta?.recordid || null,
|
|
4335
|
+
dependency_fields: func.runtime.render.sort_tree_debug_value(treeP.meta?.dependency_fields || null),
|
|
4336
|
+
iterate_info: func.runtime.render.sort_tree_debug_value(treeP.meta?.iterate_info || null),
|
|
4337
|
+
controls: func.runtime.render.sort_tree_debug_value(treeP.meta?.controls || null),
|
|
4338
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta?.capabilities || null),
|
|
4339
|
+
widget: treeP.meta?.widget
|
|
4340
|
+
? {
|
|
4341
|
+
plugin_name: treeP.meta.widget.plugin_name,
|
|
4342
|
+
method: treeP.meta.widget.method,
|
|
4343
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta.widget.capabilities || null),
|
|
4344
|
+
}
|
|
4345
|
+
: null,
|
|
4346
|
+
source_node_id: treeP.meta?.source_node_id || null,
|
|
4347
|
+
},
|
|
4348
|
+
};
|
|
4349
|
+
};
|
|
4350
|
+
func.runtime.render.serialize_tree = function (treeP, spacing = 2) {
|
|
4351
|
+
return JSON.stringify(func.runtime.render.sanitize_tree_for_debug(treeP), null, spacing);
|
|
4352
|
+
};
|
|
4353
|
+
func.runtime = func.runtime || {};
|
|
4354
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
4355
|
+
func.runtime.render = func.runtime.render || {};
|
|
4356
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
4357
|
+
|
|
4358
|
+
// Shared string-renderer helpers live here so headless/server runtimes can materialize the render tree without a DOM.
|
|
4359
|
+
|
|
4360
|
+
func.runtime.render.HTML_VOID_TAGS = func.runtime.render.HTML_VOID_TAGS || {
|
|
4361
|
+
area: true,
|
|
4362
|
+
base: true,
|
|
4363
|
+
br: true,
|
|
4364
|
+
col: true,
|
|
4365
|
+
embed: true,
|
|
4366
|
+
hr: true,
|
|
4367
|
+
img: true,
|
|
4368
|
+
input: true,
|
|
4369
|
+
link: true,
|
|
4370
|
+
meta: true,
|
|
4371
|
+
param: true,
|
|
4372
|
+
source: true,
|
|
4373
|
+
track: true,
|
|
4374
|
+
wbr: true,
|
|
4375
|
+
};
|
|
4376
|
+
func.runtime.render.escape_html = function (value) {
|
|
4377
|
+
return `${value ?? ''}`
|
|
4378
|
+
.replaceAll('&', '&')
|
|
4379
|
+
.replaceAll('<', '<')
|
|
4380
|
+
.replaceAll('>', '>')
|
|
4381
|
+
.replaceAll('"', '"')
|
|
4382
|
+
.replaceAll("'", ''');
|
|
4383
|
+
};
|
|
4384
|
+
func.runtime.render.escape_html_attribute = function (value) {
|
|
4385
|
+
return func.runtime.render.escape_html(value);
|
|
4386
|
+
};
|
|
4387
|
+
func.runtime.render.is_html_void_tag = function (tag_name) {
|
|
4388
|
+
return !!func.runtime.render.HTML_VOID_TAGS[(tag_name || '').toLowerCase()];
|
|
4389
|
+
};
|
|
4390
|
+
func.runtime.render.is_falsey_render_value = function (value) {
|
|
4391
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
4392
|
+
return true;
|
|
4393
|
+
}
|
|
4394
|
+
if (typeof value === 'number') {
|
|
4395
|
+
return value === 0;
|
|
4396
|
+
}
|
|
4397
|
+
if (typeof value === 'string') {
|
|
4398
|
+
const normalized = value.trim().toLowerCase();
|
|
4399
|
+
return normalized === '' || normalized === 'false' || normalized === '0' || normalized === 'null' || normalized === 'undefined' || normalized === 'off' || normalized === 'no';
|
|
4400
|
+
}
|
|
4401
|
+
return false;
|
|
4402
|
+
};
|
|
4403
|
+
func.runtime.render.should_render_tree_node = function (treeP) {
|
|
4404
|
+
const controls = treeP?.meta?.controls || {};
|
|
4405
|
+
if (controls.xu_if !== null && controls.xu_if !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_if)) {
|
|
4406
|
+
return false;
|
|
4407
|
+
}
|
|
4408
|
+
if (controls.xu_render !== null && controls.xu_render !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_render)) {
|
|
4409
|
+
return false;
|
|
4410
|
+
}
|
|
4411
|
+
return true;
|
|
4412
|
+
};
|
|
4413
|
+
func.runtime.render.is_tree_control_attribute = function (key) {
|
|
4414
|
+
if (!key) {
|
|
4415
|
+
return false;
|
|
4416
|
+
}
|
|
4417
|
+
return (
|
|
4418
|
+
key.startsWith('xu-exp:') ||
|
|
4419
|
+
key === 'xu-widget' ||
|
|
4420
|
+
key === 'xu-method' ||
|
|
4421
|
+
key === 'xu-for' ||
|
|
4422
|
+
key === 'xu-for-key' ||
|
|
4423
|
+
key === 'xu-for-val' ||
|
|
4424
|
+
key === 'xu-if' ||
|
|
4425
|
+
key === 'xu-render' ||
|
|
4426
|
+
key === 'xu-bind' ||
|
|
4427
|
+
key === 'xu-content' ||
|
|
4428
|
+
key === 'xu-text' ||
|
|
4429
|
+
key === 'xu-html' ||
|
|
4430
|
+
key === 'xu-show' ||
|
|
4431
|
+
key === 'xu-panel-program' ||
|
|
4432
|
+
key === 'xu-teleport'
|
|
4433
|
+
);
|
|
4434
|
+
};
|
|
4435
|
+
func.runtime.render.get_string_renderer_tag_name = function (treeP) {
|
|
4436
|
+
switch (treeP?.kind) {
|
|
4437
|
+
case 'widget':
|
|
4438
|
+
case 'single_view':
|
|
4439
|
+
case 'multi_view':
|
|
4440
|
+
case 'panel':
|
|
4441
|
+
case 'teleport':
|
|
4442
|
+
return 'div';
|
|
4443
|
+
case 'placeholder':
|
|
4444
|
+
return null;
|
|
4445
|
+
case 'text':
|
|
4446
|
+
return null;
|
|
4447
|
+
default:
|
|
4448
|
+
return treeP?.tagName || 'div';
|
|
4449
|
+
}
|
|
4450
|
+
};
|
|
4451
|
+
func.runtime.render.get_tree_terminal_content = function (treeP) {
|
|
4452
|
+
const attributes = treeP?.attributes || {};
|
|
4453
|
+
if (typeof attributes['xu-html'] !== 'undefined' && attributes['xu-html'] !== null) {
|
|
4454
|
+
return {
|
|
4455
|
+
value: `${attributes['xu-html']}`,
|
|
4456
|
+
mode: 'html',
|
|
4457
|
+
};
|
|
4458
|
+
}
|
|
4459
|
+
if (typeof attributes['xu-content'] !== 'undefined' && attributes['xu-content'] !== null) {
|
|
4460
|
+
return {
|
|
4461
|
+
value: `${attributes['xu-content']}`,
|
|
4462
|
+
mode: 'html',
|
|
4463
|
+
};
|
|
4464
|
+
}
|
|
4465
|
+
if (typeof attributes['xu-text'] !== 'undefined' && attributes['xu-text'] !== null) {
|
|
4466
|
+
return {
|
|
4467
|
+
value: `${attributes['xu-text']}`,
|
|
4468
|
+
mode: 'text',
|
|
4469
|
+
};
|
|
4470
|
+
}
|
|
4471
|
+
if (treeP?.kind === 'text') {
|
|
4472
|
+
return {
|
|
4473
|
+
value: typeof treeP?.text !== 'undefined' && treeP?.text !== null ? `${treeP.text}` : `${treeP?.content || ''}`,
|
|
4474
|
+
mode: 'text',
|
|
4475
|
+
};
|
|
4476
|
+
}
|
|
4477
|
+
return null;
|
|
4478
|
+
};
|
|
4479
|
+
func.runtime.render.render_tree_terminal_content = function (treeP) {
|
|
4480
|
+
const terminal = func.runtime.render.get_tree_terminal_content(treeP);
|
|
4481
|
+
if (!terminal) {
|
|
4482
|
+
return null;
|
|
4483
|
+
}
|
|
4484
|
+
if (terminal.mode === 'html') {
|
|
4485
|
+
return terminal.value;
|
|
4486
|
+
}
|
|
4487
|
+
return func.runtime.render.escape_html(terminal.value);
|
|
4488
|
+
};
|
|
4489
|
+
func.runtime.render.get_widget_fallback_markup = function (treeP) {
|
|
4490
|
+
const widget_meta = treeP?.meta?.widget || {};
|
|
4491
|
+
const capability_state = widget_meta?.capabilities?.headless ? 'headless-capable' : 'browser-only';
|
|
4492
|
+
return `<!--xuda-widget:${func.runtime.render.escape_html(widget_meta.plugin_name || 'unknown')}:${capability_state}-->`;
|
|
4493
|
+
};
|
|
4494
|
+
func.runtime.render.get_tree_string_attributes = function (treeP, renderer_context) {
|
|
4495
|
+
const attributes = func.runtime.render.safe_clone_tree_value(treeP?.attributes || {});
|
|
4496
|
+
const attr_pairs = [];
|
|
4497
|
+
const keys = Object.keys(attributes);
|
|
4498
|
+
|
|
4499
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4500
|
+
const key = keys[index];
|
|
4501
|
+
if (func.runtime.render.is_tree_control_attribute(key)) {
|
|
4502
|
+
continue;
|
|
4503
|
+
}
|
|
4504
|
+
const value = attributes[key];
|
|
4505
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
4506
|
+
continue;
|
|
4507
|
+
}
|
|
4508
|
+
if (value === true) {
|
|
4509
|
+
attr_pairs.push(key);
|
|
4510
|
+
continue;
|
|
4511
|
+
}
|
|
4512
|
+
const normalized_value = typeof value === 'object' ? JSON.stringify(value) : `${value}`;
|
|
4513
|
+
attr_pairs.push(`${key}="${func.runtime.render.escape_html_attribute(normalized_value)}"`);
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4516
|
+
attr_pairs.push(`data-xuda-kind="${func.runtime.render.escape_html_attribute(treeP?.kind || 'element')}"`);
|
|
4517
|
+
attr_pairs.push(`data-xuda-node-id="${func.runtime.render.escape_html_attribute(treeP?.id || treeP?.meta?.source_node_id || '')}"`);
|
|
4518
|
+
attr_pairs.push(`data-xuda-tree-id="${func.runtime.render.escape_html_attribute(treeP?.meta?.tree_id || '')}"`);
|
|
4519
|
+
|
|
4520
|
+
if (treeP?.kind === 'widget' && treeP?.meta?.widget) {
|
|
4521
|
+
attr_pairs.push(`data-xuda-widget="${func.runtime.render.escape_html_attribute(treeP.meta.widget.plugin_name || '')}"`);
|
|
4522
|
+
attr_pairs.push(`data-xuda-widget-method="${func.runtime.render.escape_html_attribute(treeP.meta.widget.method || '_default')}"`);
|
|
4523
|
+
attr_pairs.push(`data-xuda-widget-capability="${func.runtime.render.escape_html_attribute(treeP.meta.widget.capabilities?.headless ? 'headless' : 'browser')}"`);
|
|
4524
|
+
}
|
|
4525
|
+
|
|
4526
|
+
if (treeP?.kind === 'teleport' && treeP?.attributes?.['xu-teleport']) {
|
|
4527
|
+
attr_pairs.push(`data-xuda-teleport-target="${func.runtime.render.escape_html_attribute(treeP.attributes['xu-teleport'])}"`);
|
|
4528
|
+
}
|
|
4529
|
+
|
|
4530
|
+
if ((treeP?.meta?.controls?.xu_for !== null && treeP?.meta?.controls?.xu_for !== undefined) && !renderer_context?.strip_iteration_markers) {
|
|
4531
|
+
attr_pairs.push('data-xuda-xu-for="pending"');
|
|
4532
|
+
}
|
|
4533
|
+
|
|
4534
|
+
return attr_pairs.length ? ' ' + attr_pairs.join(' ') : '';
|
|
4535
|
+
};
|
|
4536
|
+
func.runtime.render.render_tree_children_to_string = async function (treeP, renderer_context) {
|
|
4537
|
+
if (!Array.isArray(treeP?.children) || !treeP.children.length) {
|
|
4538
|
+
return '';
|
|
4539
|
+
}
|
|
4540
|
+
let html = '';
|
|
4541
|
+
for (let index = 0; index < treeP.children.length; index++) {
|
|
4542
|
+
html += await func.runtime.render.render_tree_to_string(treeP.children[index], {
|
|
4543
|
+
...renderer_context,
|
|
4544
|
+
parent_tree: treeP,
|
|
4545
|
+
});
|
|
4546
|
+
}
|
|
4547
|
+
return html;
|
|
4548
|
+
};
|
|
4549
|
+
func.runtime.render.render_tree_to_string = async function (treeP, renderer_context = {}) {
|
|
4550
|
+
if (!treeP) {
|
|
4551
|
+
return '';
|
|
4552
|
+
}
|
|
4553
|
+
if (Array.isArray(treeP)) {
|
|
4554
|
+
let html = '';
|
|
4555
|
+
for (let index = 0; index < treeP.length; index++) {
|
|
4556
|
+
html += await func.runtime.render.render_tree_to_string(treeP[index], renderer_context);
|
|
4557
|
+
}
|
|
4558
|
+
return html;
|
|
4559
|
+
}
|
|
4560
|
+
|
|
4561
|
+
const ensured_tree = await func.runtime.render.ensure_tree_node({
|
|
4562
|
+
SESSION_ID: renderer_context?.SESSION_ID,
|
|
4563
|
+
nodeP: treeP,
|
|
4564
|
+
paramsP: renderer_context?.paramsP,
|
|
4565
|
+
parent_infoP: renderer_context?.parent_infoP,
|
|
4566
|
+
keyP: renderer_context?.keyP,
|
|
4567
|
+
parent_nodeP: renderer_context?.parent_nodeP,
|
|
4568
|
+
});
|
|
4569
|
+
|
|
4570
|
+
if (!ensured_tree || !func.runtime.render.should_render_tree_node(ensured_tree)) {
|
|
4571
|
+
return '';
|
|
4572
|
+
}
|
|
4573
|
+
|
|
4574
|
+
if (ensured_tree.kind === 'placeholder') {
|
|
4575
|
+
if (renderer_context?.include_placeholders) {
|
|
4576
|
+
return `<!--xuda-placeholder:${func.runtime.render.escape_html(ensured_tree.id || '')}-->`;
|
|
4577
|
+
}
|
|
4578
|
+
return '';
|
|
4579
|
+
}
|
|
4580
|
+
|
|
4581
|
+
if (ensured_tree.kind === 'text') {
|
|
4582
|
+
return func.runtime.render.render_tree_terminal_content(ensured_tree) || '';
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
const tag_name = func.runtime.render.get_string_renderer_tag_name(ensured_tree);
|
|
4586
|
+
if (!tag_name || tag_name.toLowerCase() === 'script') {
|
|
4587
|
+
return '';
|
|
4588
|
+
}
|
|
4589
|
+
|
|
4590
|
+
const attributes = func.runtime.render.get_tree_string_attributes(ensured_tree, renderer_context);
|
|
4591
|
+
const terminal_content = func.runtime.render.render_tree_terminal_content(ensured_tree);
|
|
4592
|
+
let children_html = terminal_content !== null ? terminal_content : await func.runtime.render.render_tree_children_to_string(ensured_tree, renderer_context);
|
|
4593
|
+
|
|
4594
|
+
if (ensured_tree.kind === 'widget' && !children_html) {
|
|
4595
|
+
children_html = func.runtime.render.get_widget_fallback_markup(ensured_tree);
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4598
|
+
if (func.runtime.render.is_html_void_tag(tag_name)) {
|
|
4599
|
+
return `<${tag_name}${attributes}>`;
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
return `<${tag_name}${attributes}>${children_html}</${tag_name}>`;
|
|
4603
|
+
};
|
|
4604
|
+
func.runtime.render.render_to_string = async function (options = {}) {
|
|
4605
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
4606
|
+
SESSION_ID: options.SESSION_ID,
|
|
4607
|
+
nodeP: options.treeP || options.nodeP,
|
|
4608
|
+
paramsP: options.paramsP,
|
|
4609
|
+
parent_infoP: options.parent_infoP,
|
|
4610
|
+
keyP: options.keyP,
|
|
4611
|
+
parent_nodeP: options.parent_nodeP,
|
|
4612
|
+
});
|
|
4613
|
+
|
|
4614
|
+
return await func.runtime.render.render_tree_to_string(treeP, options);
|
|
4615
|
+
};
|
|
4616
|
+
func.runtime.render.get_server_render_mode = function (options = {}) {
|
|
4617
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap({
|
|
4618
|
+
app_computing_mode: options.app_computing_mode,
|
|
4619
|
+
app_render_mode: options.app_render_mode,
|
|
4620
|
+
app_client_activation: options.app_client_activation,
|
|
4621
|
+
});
|
|
4622
|
+
|
|
4623
|
+
return normalized;
|
|
4624
|
+
};
|
|
4625
|
+
func.runtime.render.build_server_render_params = async function (options = {}) {
|
|
4626
|
+
const SESSION_ID = options.SESSION_ID;
|
|
4627
|
+
const prog_id = options.prog_id;
|
|
4628
|
+
const dsSessionP = options.dsSessionP;
|
|
4629
|
+
const _session = SESSION_OBJ?.[SESSION_ID] || {};
|
|
4630
|
+
const _ds = _session?.DS_GLB?.[dsSessionP] || {};
|
|
4631
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
4632
|
+
|
|
4633
|
+
if (!viewDoc?.properties) {
|
|
4634
|
+
throw new Error(`view document not found for ${prog_id}`);
|
|
4635
|
+
}
|
|
4636
|
+
|
|
4637
|
+
const base_params = _ds?.screen_params ? func.runtime.render.safe_clone_tree_value(_ds.screen_params) : {};
|
|
4638
|
+
const screenId = options.screenId || base_params.screenId || `ssr_${prog_id}_${dsSessionP || '0'}`;
|
|
4639
|
+
const paramsP = {
|
|
4640
|
+
...base_params,
|
|
4641
|
+
prog_id,
|
|
4642
|
+
sourceScreenP: null,
|
|
4643
|
+
$callingContainerP: null,
|
|
4644
|
+
triggerIdP: null,
|
|
4645
|
+
callingDataSource_objP: _ds,
|
|
4646
|
+
rowIdP: typeof options.rowIdP !== 'undefined' ? options.rowIdP : (_ds?.currentRecordId || null),
|
|
4647
|
+
renderType: viewDoc.properties?.renderType,
|
|
4648
|
+
parameters_obj_inP: options.parameters_obj_inP || base_params.parameters_obj_inP || options.parameters_raw_obj || {},
|
|
4649
|
+
source_functionP: options.source_functionP || base_params.source_functionP || 'render_string',
|
|
4650
|
+
is_panelP: false,
|
|
4651
|
+
screen_type: options.screen_type || base_params.screen_type || 'render_string',
|
|
4652
|
+
screenInfo: viewDoc,
|
|
4653
|
+
call_screen_propertiesP: base_params.call_screen_propertiesP,
|
|
4654
|
+
parentDataSourceNoP: typeof _ds?.parentDataSourceNo === 'undefined' || _ds?.parentDataSourceNo === null ? 0 : _ds.parentDataSourceNo,
|
|
4655
|
+
parameters_raw_obj: options.parameters_raw_obj || base_params.parameters_raw_obj || {},
|
|
4656
|
+
dsSessionP,
|
|
4657
|
+
screenId,
|
|
4658
|
+
containerIdP: base_params.containerIdP || `ssr_container_${screenId}`,
|
|
4659
|
+
};
|
|
4660
|
+
|
|
4661
|
+
if (_ds) {
|
|
4662
|
+
_ds.screen_params = paramsP;
|
|
4663
|
+
}
|
|
4664
|
+
|
|
4665
|
+
return paramsP;
|
|
4666
|
+
};
|
|
4667
|
+
func.runtime.render.build_prog_tree = async function (options = {}) {
|
|
4668
|
+
const SESSION_ID = options.SESSION_ID;
|
|
4669
|
+
const prog_id = options.prog_id;
|
|
4670
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
4671
|
+
|
|
4672
|
+
if (!viewDoc?.progUi?.length) {
|
|
4673
|
+
throw new Error(`progUi not found for ${prog_id}`);
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4676
|
+
const paramsP = options.paramsP || (await func.runtime.render.build_server_render_params({
|
|
4677
|
+
...options,
|
|
4678
|
+
SESSION_ID,
|
|
4679
|
+
prog_id,
|
|
4680
|
+
viewDoc,
|
|
4681
|
+
}));
|
|
4682
|
+
const root_index = typeof options.root_index === 'number' ? options.root_index : 0;
|
|
4683
|
+
const root_node = func.runtime.render.safe_clone_tree_value(viewDoc.progUi[root_index]);
|
|
4684
|
+
const tree = await func.runtime.render.build_tree({
|
|
4685
|
+
SESSION_ID,
|
|
4686
|
+
nodeP: root_node,
|
|
4687
|
+
paramsP,
|
|
4688
|
+
});
|
|
4689
|
+
|
|
4690
|
+
return {
|
|
4691
|
+
tree,
|
|
4692
|
+
paramsP,
|
|
4693
|
+
viewDoc,
|
|
4694
|
+
};
|
|
4695
|
+
};
|
|
4696
|
+
func.runtime.render.build_ssr_payload = function (render_program, options = {}) {
|
|
4697
|
+
const runtime_profile = func.runtime.render.get_server_render_mode(options);
|
|
4698
|
+
return {
|
|
4699
|
+
contract: 'xuda.ssr.v1',
|
|
4700
|
+
prog_id: options.prog_id,
|
|
4701
|
+
screenId: render_program.paramsP.screenId,
|
|
4702
|
+
containerId: render_program.paramsP.containerIdP,
|
|
4703
|
+
app_computing_mode: runtime_profile.app_computing_mode,
|
|
4704
|
+
app_render_mode: runtime_profile.app_render_mode,
|
|
4705
|
+
app_client_activation: runtime_profile.app_client_activation,
|
|
4706
|
+
tree_contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
4707
|
+
};
|
|
4708
|
+
};
|
|
4709
|
+
func.runtime.render.build_ssr_screen_html = function (html, render_program, options = {}) {
|
|
4710
|
+
const payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
4711
|
+
const screenId = func.runtime.render.escape_html_attribute(payload.screenId || '');
|
|
4712
|
+
const containerId = func.runtime.render.escape_html_attribute(payload.containerId || '');
|
|
4713
|
+
const activation = func.runtime.render.escape_html_attribute(payload.app_client_activation || 'takeover');
|
|
4714
|
+
|
|
4715
|
+
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>`;
|
|
4716
|
+
};
|
|
4717
|
+
func.runtime.render.render_prog_to_string = async function (options = {}) {
|
|
4718
|
+
const render_program = await func.runtime.render.build_prog_tree(options);
|
|
4719
|
+
const html = await func.runtime.render.render_to_string({
|
|
4720
|
+
...options,
|
|
4721
|
+
SESSION_ID: options.SESSION_ID,
|
|
4722
|
+
treeP: render_program.tree,
|
|
4723
|
+
paramsP: render_program.paramsP,
|
|
4724
|
+
});
|
|
4725
|
+
const ssr_payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
4726
|
+
const screen_html = func.runtime.render.build_ssr_screen_html(html, render_program, options);
|
|
3801
4727
|
|
|
3802
|
-
|
|
3803
|
-
|
|
4728
|
+
return {
|
|
4729
|
+
prog_id: options.prog_id,
|
|
4730
|
+
dsSessionP: render_program.paramsP.dsSessionP,
|
|
4731
|
+
screenId: render_program.paramsP.screenId,
|
|
4732
|
+
html,
|
|
4733
|
+
screen_html,
|
|
4734
|
+
tree_json: func.runtime.render.serialize_tree(render_program.tree),
|
|
4735
|
+
paramsP: render_program.paramsP,
|
|
4736
|
+
ssr_payload,
|
|
4737
|
+
};
|
|
4738
|
+
};
|
|
4739
|
+
func.runtime = func.runtime || {};
|
|
4740
|
+
func.runtime.platform = func.runtime.platform || {};
|
|
3804
4741
|
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
4742
|
+
func.runtime.platform.dispatch_document_event = function (name, data) {
|
|
4743
|
+
if (typeof document === 'undefined' || typeof CustomEvent === 'undefined') {
|
|
4744
|
+
return false;
|
|
3809
4745
|
}
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
4746
|
+
document.dispatchEvent(new CustomEvent(name, {
|
|
4747
|
+
detail: Array.isArray(data) ? data : [data],
|
|
4748
|
+
}));
|
|
4749
|
+
return true;
|
|
3813
4750
|
};
|
|
3814
|
-
|
|
3815
|
-
glb.new_xu_render = false;
|
|
3816
4751
|
glb.DEBUG_INFO_OBJ = {};
|
|
3817
4752
|
// var CONNECTION_ATTEMPTS = 0;
|
|
3818
4753
|
glb.APP_INFO = {};
|
|
@@ -9190,6 +10125,15 @@ func.runtime.ui.ensure_embed_container = function (SESSION_ID) {
|
|
|
9190
10125
|
const $root_element = func.runtime.ui.get_root_element(SESSION_ID);
|
|
9191
10126
|
let $embed_container = func.runtime.ui.find_by_selector($root_element, `#embed_${SESSION_ID}`, true);
|
|
9192
10127
|
|
|
10128
|
+
if (!$embed_container.length) {
|
|
10129
|
+
const $ssr_embed_container = func.runtime.ui.find_by_selector($root_element, `[data-xuda-ssr-embed="true"]`, true);
|
|
10130
|
+
const ssr_embed_node = func.runtime.ui.get_first_node($ssr_embed_container);
|
|
10131
|
+
if (ssr_embed_node) {
|
|
10132
|
+
ssr_embed_node.id = 'embed_' + SESSION_ID;
|
|
10133
|
+
$embed_container = func.runtime.ui._wrap_matches([ssr_embed_node]);
|
|
10134
|
+
}
|
|
10135
|
+
}
|
|
10136
|
+
|
|
9193
10137
|
if (!$embed_container.length) {
|
|
9194
10138
|
const embed_node = document.createElement('div');
|
|
9195
10139
|
embed_node.id = 'embed_' + SESSION_ID;
|
|
@@ -9225,12 +10169,44 @@ func.runtime.ui.get_root_tag_name = function () {
|
|
|
9225
10169
|
}
|
|
9226
10170
|
return root_tag_name;
|
|
9227
10171
|
};
|
|
10172
|
+
func.runtime.ui.find_ssr_screen_host = function ($container, screenId, containerId) {
|
|
10173
|
+
const container_node = func.runtime.ui.get_first_node($container);
|
|
10174
|
+
if (!container_node || !screenId) {
|
|
10175
|
+
return null;
|
|
10176
|
+
}
|
|
10177
|
+
|
|
10178
|
+
const dialog_node =
|
|
10179
|
+
container_node.querySelector?.(`#${CSS?.escape ? CSS.escape(screenId) : screenId}`) ||
|
|
10180
|
+
container_node.querySelector?.(`[data-xuda-ssr-screen-id="${screenId}"]`);
|
|
10181
|
+
if (!dialog_node) {
|
|
10182
|
+
return null;
|
|
10183
|
+
}
|
|
10184
|
+
|
|
10185
|
+
const root_frame_node =
|
|
10186
|
+
(containerId ? dialog_node.querySelector?.(`#${CSS?.escape ? CSS.escape(containerId) : containerId}`) : null) ||
|
|
10187
|
+
dialog_node.querySelector?.('[data-xuda-ssr-root-frame="true"]');
|
|
10188
|
+
if (!root_frame_node) {
|
|
10189
|
+
return null;
|
|
10190
|
+
}
|
|
10191
|
+
|
|
10192
|
+
return {
|
|
10193
|
+
$dialogDiv: func.runtime.ui._wrap_matches([dialog_node]),
|
|
10194
|
+
$rootFrame: func.runtime.ui._wrap_matches([root_frame_node]),
|
|
10195
|
+
reused_ssr_host: true,
|
|
10196
|
+
};
|
|
10197
|
+
};
|
|
9228
10198
|
func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params, $callingContainerP, screenId) {
|
|
9229
10199
|
var $dialogDiv;
|
|
9230
10200
|
var $rootFrame;
|
|
10201
|
+
let reused_ssr_host = false;
|
|
9231
10202
|
|
|
9232
10203
|
switch (screen_type) {
|
|
9233
10204
|
case 'embed': {
|
|
10205
|
+
const ssr_host = func.runtime.ui.find_ssr_screen_host($callingContainerP, screenId, params?.containerIdP);
|
|
10206
|
+
if (ssr_host) {
|
|
10207
|
+
return ssr_host;
|
|
10208
|
+
}
|
|
10209
|
+
|
|
9234
10210
|
const dialogNode = document.createElement('div');
|
|
9235
10211
|
dialogNode.id = screenId;
|
|
9236
10212
|
dialogNode.setAttribute('ui_engine', UI_FRAMEWORK_INSTALLED);
|
|
@@ -9280,6 +10256,7 @@ func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params,
|
|
|
9280
10256
|
return {
|
|
9281
10257
|
$dialogDiv,
|
|
9282
10258
|
$rootFrame,
|
|
10259
|
+
reused_ssr_host,
|
|
9283
10260
|
};
|
|
9284
10261
|
};
|
|
9285
10262
|
func.runtime.ui.find_xu_ui_in_root = function (SESSION_ID, xu_ui_id) {
|
|
@@ -9313,7 +10290,7 @@ func.runtime.ui.find_element_data_in_root = function (SESSION_ID, dataKey, prope
|
|
|
9313
10290
|
}
|
|
9314
10291
|
return func.runtime.ui.find_in_root(SESSION_ID, '[xu-panel-wrapper-id]');
|
|
9315
10292
|
}
|
|
9316
|
-
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui.
|
|
10293
|
+
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui.get_root_element(SESSION_ID), property, value);
|
|
9317
10294
|
};
|
|
9318
10295
|
func.runtime.ui.find_element_data_in_parent = function ($container, dataKey, property, value) {
|
|
9319
10296
|
const container_node = func.runtime.ui.get_first_node($container);
|
|
@@ -9327,7 +10304,7 @@ func.runtime.ui.find_element_data_in_parent = function ($container, dataKey, pro
|
|
|
9327
10304
|
}
|
|
9328
10305
|
return func.runtime.ui.find_by_selector(parent_node, `[xu-ui-id="${value}"]`);
|
|
9329
10306
|
}
|
|
9330
|
-
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui.
|
|
10307
|
+
return func.UI.utils.find_in_element_data(dataKey, func.runtime.ui._wrap_matches([parent_node]), property, value);
|
|
9331
10308
|
};
|
|
9332
10309
|
func.runtime.ui.sync_child_parent_container = function ($div) {
|
|
9333
10310
|
const div_node = func.runtime.ui.get_first_node($div);
|
|
@@ -9434,40 +10411,14 @@ func.runtime.ui.clear_screen_blockers = function () {
|
|
|
9434
10411
|
}
|
|
9435
10412
|
};
|
|
9436
10413
|
|
|
9437
|
-
// @deprecated — no-op shim now that jQuery is removed from the bundle.
|
|
9438
10414
|
func.runtime.ui.as_jquery = function (target) {
|
|
9439
|
-
if (target?.jquery) {
|
|
9440
|
-
return target;
|
|
9441
|
-
}
|
|
9442
10415
|
const node = func.runtime.ui.get_first_node(target);
|
|
9443
|
-
|
|
9444
|
-
const _node_data = {};
|
|
9445
|
-
const _arr = node ? [node] : [];
|
|
9446
|
-
return {
|
|
9447
|
-
0: node,
|
|
9448
|
-
length: _arr.length,
|
|
9449
|
-
toArray: function () { return _arr.slice(); },
|
|
9450
|
-
data: function (key, value) {
|
|
9451
|
-
if (typeof key === 'undefined') return _node_data;
|
|
9452
|
-
if (typeof value !== 'undefined') { _node_data[key] = value; return this; }
|
|
9453
|
-
return _node_data[key];
|
|
9454
|
-
},
|
|
9455
|
-
attr: function (key, value) {
|
|
9456
|
-
if (!node) return undefined;
|
|
9457
|
-
if (typeof value !== 'undefined') { node.setAttribute(key, value); return this; }
|
|
9458
|
-
return node?.getAttribute?.(key);
|
|
9459
|
-
},
|
|
9460
|
-
removeData: function () { for (const k in _node_data) delete _node_data[k]; return this; },
|
|
9461
|
-
children: function () { return { toArray: function () { return node ? Array.from(node.children) : []; } }; },
|
|
9462
|
-
};
|
|
10416
|
+
return func.runtime.ui._wrap_matches(node ? [node] : []);
|
|
9463
10417
|
};
|
|
9464
10418
|
func.runtime.ui.get_first_node = function (target) {
|
|
9465
10419
|
if (!target) {
|
|
9466
10420
|
return null;
|
|
9467
10421
|
}
|
|
9468
|
-
if (target?.jquery) {
|
|
9469
|
-
return target[0] || null;
|
|
9470
|
-
}
|
|
9471
10422
|
if (target?.nodeType) {
|
|
9472
10423
|
return target;
|
|
9473
10424
|
}
|
|
@@ -9485,9 +10436,10 @@ func.runtime.ui.get_data = function (target) {
|
|
|
9485
10436
|
if (meta) return meta;
|
|
9486
10437
|
}
|
|
9487
10438
|
}
|
|
9488
|
-
// fallback: store per-element data on the node itself
|
|
9489
10439
|
if (target_node) {
|
|
9490
|
-
if (!target_node.__xuData)
|
|
10440
|
+
if (!target_node.__xuData) {
|
|
10441
|
+
target_node.__xuData = {};
|
|
10442
|
+
}
|
|
9491
10443
|
return target_node.__xuData;
|
|
9492
10444
|
}
|
|
9493
10445
|
return {};
|
|
@@ -9869,6 +10821,11 @@ func.runtime.ui.build_container_xu_data = function (options) {
|
|
|
9869
10821
|
func.runtime.ui.apply_container_meta = function ($div, options) {
|
|
9870
10822
|
const div_node = func.runtime.ui.get_first_node($div);
|
|
9871
10823
|
func.runtime.ui.set_attr(div_node, 'xu-ui-id', options.ui_id);
|
|
10824
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-kind', options.treeP?.kind || options.nodeP?.tagName || 'element');
|
|
10825
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-node-id', options.nodeP?.id || options.nodeP?.id_org || '');
|
|
10826
|
+
if (options.treeP?.meta?.tree_id !== null && typeof options.treeP?.meta?.tree_id !== 'undefined') {
|
|
10827
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-tree-id', options.treeP.meta.tree_id);
|
|
10828
|
+
}
|
|
9872
10829
|
const xuData = func.runtime.ui.build_container_xu_data(options);
|
|
9873
10830
|
if (options.parent_infoP?.iterate_info) {
|
|
9874
10831
|
xuData.iterate_info = options.parent_infoP.iterate_info;
|
|
@@ -9963,6 +10920,38 @@ func.runtime.ui.create_container_element = function (div_typeP, attr_str, prop,
|
|
|
9963
10920
|
}
|
|
9964
10921
|
return func.runtime.ui.create_element(div, attr_str);
|
|
9965
10922
|
};
|
|
10923
|
+
func.runtime.ui.find_hydration_candidate = function (options) {
|
|
10924
|
+
if (!func.runtime.render.is_hydration_mode(SESSION_OBJ?.[options.SESSION_ID])) {
|
|
10925
|
+
return null;
|
|
10926
|
+
}
|
|
10927
|
+
if (!func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
10928
|
+
return null;
|
|
10929
|
+
}
|
|
10930
|
+
if (options.is_placeholder || !options.treeP?.meta?.tree_id) {
|
|
10931
|
+
return null;
|
|
10932
|
+
}
|
|
10933
|
+
|
|
10934
|
+
const append_node = func.runtime.ui.get_first_node(options.$appendTo || options.$container);
|
|
10935
|
+
if (!append_node) {
|
|
10936
|
+
return null;
|
|
10937
|
+
}
|
|
10938
|
+
|
|
10939
|
+
const children = func.runtime.ui.get_children(append_node);
|
|
10940
|
+
for (let index = 0; index < children.length; index++) {
|
|
10941
|
+
const child = children[index];
|
|
10942
|
+
if (child?.__xuda_hydration_claimed) {
|
|
10943
|
+
continue;
|
|
10944
|
+
}
|
|
10945
|
+
if (func.runtime.ui.get_attr(child, 'data-xuda-tree-id') !== `${options.treeP.meta.tree_id}`) {
|
|
10946
|
+
continue;
|
|
10947
|
+
}
|
|
10948
|
+
child.__xuda_hydration_claimed = true;
|
|
10949
|
+
func.runtime.ui.set_attr(child, 'data-xuda-client-activation', 'hydrate');
|
|
10950
|
+
return child;
|
|
10951
|
+
}
|
|
10952
|
+
|
|
10953
|
+
return null;
|
|
10954
|
+
};
|
|
9966
10955
|
func.runtime.ui.build_xu_ui_id_seed = function (nodeP, dsSessionP, key_path, currentRecordId) {
|
|
9967
10956
|
const nodeId = nodeP.xu_tree_id || nodeP.id;
|
|
9968
10957
|
const elem_key = `${nodeId}-${key_path}-${currentRecordId}`;
|
|
@@ -10015,7 +11004,11 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
10015
11004
|
try {
|
|
10016
11005
|
const key_path = func.runtime.ui.build_container_key_path(container_xu_data, options.keyP, options.parent_infoP, options.nodeP, options.parent_nodeP);
|
|
10017
11006
|
const elem_key = `${options.nodeP.xu_tree_id || options.nodeP.id}-${key_path}-${currentRecordId}`;
|
|
10018
|
-
const
|
|
11007
|
+
const hydration_candidate = func.runtime.ui.find_hydration_candidate({
|
|
11008
|
+
...options,
|
|
11009
|
+
$appendTo,
|
|
11010
|
+
});
|
|
11011
|
+
const $div = hydration_candidate || func.runtime.ui.create_container_element(options.div_typeP, options.attr_str, options.prop, options.nodeP, $appendTo);
|
|
10019
11012
|
const new_ui_id = await func.runtime.ui.generate_xu_ui_id(options.SESSION_ID, options.nodeP, options.$container, options.paramsP, options.keyP, {
|
|
10020
11013
|
container_xu_data,
|
|
10021
11014
|
currentRecordId,
|
|
@@ -10041,9 +11034,10 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
10041
11034
|
parent_infoP: options.parent_infoP,
|
|
10042
11035
|
is_placeholder: options.is_placeholder,
|
|
10043
11036
|
classP: options.classP,
|
|
11037
|
+
treeP: options.treeP,
|
|
10044
11038
|
});
|
|
10045
11039
|
|
|
10046
|
-
if (options.div_typeP !== 'svg') {
|
|
11040
|
+
if (!hydration_candidate && options.div_typeP !== 'svg') {
|
|
10047
11041
|
func.runtime.ui.append_to($div, $appendTo);
|
|
10048
11042
|
}
|
|
10049
11043
|
return $div;
|
|
@@ -12724,9 +13718,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12724
13718
|
|
|
12725
13719
|
const _session = SESSION_OBJ[SESSION_ID];
|
|
12726
13720
|
const screenInfo = structuredClone(screen_ret);
|
|
13721
|
+
const ssr_payload = func.runtime.render.should_use_ssr_payload(SESSION_ID, { prog_id }) ? func.runtime.render.get_ssr_payload(_session) : null;
|
|
12727
13722
|
|
|
12728
13723
|
const screen_type = source_functionP?.split('_')?.[1];
|
|
12729
|
-
const screenId = (glb.screen_num++).toString();
|
|
13724
|
+
const screenId = ssr_payload?.screenId || (glb.screen_num++).toString();
|
|
12730
13725
|
|
|
12731
13726
|
if (SCREEN_BLOCKER_OBJ[prog_id + (sourceScreenP ? '_' + sourceScreenP : '')]) {
|
|
12732
13727
|
const wait_for_SCREEN_BLOCKER_release = function () {
|
|
@@ -12768,6 +13763,8 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12768
13763
|
call_screen_propertiesP,
|
|
12769
13764
|
parentDataSourceNoP: _session.DS_GLB?.[callingDataSource_objP?.dsSession]?.dsSession || callingDataSource_objP?.parentDataSourceNo || 0,
|
|
12770
13765
|
parameters_raw_obj,
|
|
13766
|
+
containerIdP: ssr_payload?.containerId || null,
|
|
13767
|
+
ssr_payload,
|
|
12771
13768
|
};
|
|
12772
13769
|
|
|
12773
13770
|
const screen_host = func.runtime.ui.create_screen_host(SESSION_ID, screen_type, params, $callingContainerP, screenId);
|
|
@@ -12800,6 +13797,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12800
13797
|
func.runtime.ui.set_style($rootFrame, 'display', 'contents');
|
|
12801
13798
|
}
|
|
12802
13799
|
|
|
13800
|
+
if (screen_host.reused_ssr_host && func.runtime.render.is_takeover_mode(_session)) {
|
|
13801
|
+
func.runtime.ui.empty($rootFrame);
|
|
13802
|
+
}
|
|
13803
|
+
|
|
12803
13804
|
if (!is_panelP) func.UI.utils.indicator.screen.busy();
|
|
12804
13805
|
|
|
12805
13806
|
const ret = await func.datasource.create(
|
|
@@ -12841,7 +13842,24 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12841
13842
|
}
|
|
12842
13843
|
let node = structuredClone(viewDoc.progUi);
|
|
12843
13844
|
if (!node.length) return console.warn('ui node empty');
|
|
12844
|
-
const
|
|
13845
|
+
const root_tree = await func.runtime.render.build_tree({
|
|
13846
|
+
SESSION_ID,
|
|
13847
|
+
nodeP: node[0],
|
|
13848
|
+
paramsP: params,
|
|
13849
|
+
});
|
|
13850
|
+
const ret_render_$container = await func.runtime.render.render_tree(root_tree, {
|
|
13851
|
+
SESSION_ID,
|
|
13852
|
+
$container: $rootFrame,
|
|
13853
|
+
parent_infoP: null,
|
|
13854
|
+
paramsP: params,
|
|
13855
|
+
jobNoP,
|
|
13856
|
+
is_skeleton: null,
|
|
13857
|
+
keyP: null,
|
|
13858
|
+
refreshed_ds: null,
|
|
13859
|
+
parent_nodeP: null,
|
|
13860
|
+
check_existP: null,
|
|
13861
|
+
$root_container: $rootFrame,
|
|
13862
|
+
});
|
|
12845
13863
|
|
|
12846
13864
|
if (!is_panelP) func.UI.utils.indicator.screen.normal();
|
|
12847
13865
|
|
|
@@ -12925,7 +13943,7 @@ func.runtime.ui.ensure_nav = function (SESSION_ID, $container) {
|
|
|
12925
13943
|
}
|
|
12926
13944
|
var nav_el = document.createElement('xu-nav');
|
|
12927
13945
|
func.runtime.ui.append($container, nav_el);
|
|
12928
|
-
var $nav = func.runtime.ui.
|
|
13946
|
+
var $nav = func.runtime.ui._wrap_matches([nav_el]);
|
|
12929
13947
|
func.UI.component.init_xu_nav($container, $nav);
|
|
12930
13948
|
return $nav;
|
|
12931
13949
|
};
|
|
@@ -13266,6 +14284,7 @@ func.runtime.ui.render_single_view_node = async function (options) {
|
|
|
13266
14284
|
parent_infoP: options.parent_infoP,
|
|
13267
14285
|
jobNoP: options.jobNoP,
|
|
13268
14286
|
keyP: options.keyP,
|
|
14287
|
+
treeP: options.treeP,
|
|
13269
14288
|
parent_nodeP: options.parent_nodeP,
|
|
13270
14289
|
prop: options.prop,
|
|
13271
14290
|
div_typeP: 'div',
|
|
@@ -13394,6 +14413,7 @@ func.runtime.ui.render_panel_node = async function (options) {
|
|
|
13394
14413
|
parent_infoP: options.parent_infoP,
|
|
13395
14414
|
jobNoP: options.jobNoP,
|
|
13396
14415
|
keyP: options.keyP,
|
|
14416
|
+
treeP: options.treeP,
|
|
13397
14417
|
parent_nodeP: options.parent_nodeP,
|
|
13398
14418
|
prop: options.prop,
|
|
13399
14419
|
$appendToP: $wrapper,
|
|
@@ -13723,6 +14743,14 @@ func.runtime.ui.screen_loading_done = async function (options) {
|
|
|
13723
14743
|
});
|
|
13724
14744
|
|
|
13725
14745
|
const _session = SESSION_OBJ[options.SESSION_ID];
|
|
14746
|
+
if (func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
14747
|
+
const root_node = func.runtime.ui.get_root_node(options.SESSION_ID);
|
|
14748
|
+
if (root_node) {
|
|
14749
|
+
func.runtime.ui.set_attr(root_node, 'data-xuda-client-activation', _session.opt.app_client_activation || 'none');
|
|
14750
|
+
func.runtime.ui.set_attr(root_node, 'data-xuda-ssr-status', _session.opt.app_client_activation === 'hydrate' ? 'hydrated' : 'taken-over');
|
|
14751
|
+
}
|
|
14752
|
+
func.runtime.render.mark_ssr_payload_consumed(options.SESSION_ID);
|
|
14753
|
+
}
|
|
13726
14754
|
func.events.delete_job(options.SESSION_ID, options.jobNoP);
|
|
13727
14755
|
func.UI.utils.screen_blocker(false, options.paramsP.prog_id + (options.paramsP.sourceScreenP ? '_' + options.paramsP.sourceScreenP : ''));
|
|
13728
14756
|
if (_session.prog_id === options.paramsP.prog_id) {
|
|
@@ -13755,7 +14783,7 @@ func.runtime.ui._to_node_array = func.runtime.ui._to_node_array || function (inp
|
|
|
13755
14783
|
if (!input) {
|
|
13756
14784
|
return [];
|
|
13757
14785
|
}
|
|
13758
|
-
if (input
|
|
14786
|
+
if (typeof input?.toArray === 'function' && typeof input?.length === 'number' && !input?.nodeType) {
|
|
13759
14787
|
return input.toArray();
|
|
13760
14788
|
}
|
|
13761
14789
|
if (Array.isArray(input)) {
|
|
@@ -15565,6 +16593,9 @@ func.runtime.render.get_screen_context = function (SESSION_ID, $container, param
|
|
|
15565
16593
|
};
|
|
15566
16594
|
func.runtime.render.get_node_attributes = function (nodeP) {
|
|
15567
16595
|
try {
|
|
16596
|
+
if (func.runtime.render.is_tree_node?.(nodeP)) {
|
|
16597
|
+
return nodeP.attributes;
|
|
16598
|
+
}
|
|
15568
16599
|
return nodeP?.attributes;
|
|
15569
16600
|
} catch (error) {
|
|
15570
16601
|
return undefined;
|
|
@@ -15682,6 +16713,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15682
16713
|
parent_infoP: options.parent_infoP,
|
|
15683
16714
|
jobNoP: options.jobNoP,
|
|
15684
16715
|
keyP: options.keyP,
|
|
16716
|
+
treeP: options.treeP,
|
|
15685
16717
|
parent_nodeP: options.parent_nodeP,
|
|
15686
16718
|
prop: options.prop,
|
|
15687
16719
|
div_typeP: options.element,
|
|
@@ -15704,6 +16736,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15704
16736
|
parent_infoP: options.parent_infoP,
|
|
15705
16737
|
jobNoP: options.jobNoP,
|
|
15706
16738
|
keyP: options.keyP,
|
|
16739
|
+
treeP: options.treeP,
|
|
15707
16740
|
parent_nodeP: options.parent_nodeP,
|
|
15708
16741
|
prop: options.prop,
|
|
15709
16742
|
div_typeP: options.element,
|
|
@@ -16560,18 +17593,28 @@ func.runtime.widgets.render_node = async function (options) {
|
|
|
16560
17593
|
parent_infoP: options.parent_infoP,
|
|
16561
17594
|
jobNoP: options.jobNoP,
|
|
16562
17595
|
keyP: options.keyP,
|
|
17596
|
+
treeP: options.treeP,
|
|
16563
17597
|
parent_nodeP: options.parent_nodeP,
|
|
16564
17598
|
prop: options.prop,
|
|
16565
17599
|
classP: 'widget_wrapper',
|
|
16566
17600
|
});
|
|
16567
17601
|
|
|
17602
|
+
if (func.runtime.render.is_hydration_mode(SESSION_OBJ?.[options.SESSION_ID]) && func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
17603
|
+
func.runtime.ui.empty($div);
|
|
17604
|
+
}
|
|
17605
|
+
|
|
16568
17606
|
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, options.prop);
|
|
16569
17607
|
const { plugin_name, method, propsP, plugin: _plugin } = widget_context;
|
|
16570
17608
|
const report_error = function (descP, warn) {
|
|
16571
17609
|
return func.runtime.widgets.report_error(widget_context, descP, warn);
|
|
16572
17610
|
};
|
|
16573
17611
|
|
|
16574
|
-
const
|
|
17612
|
+
const definition = await func.runtime.widgets.get_definition(widget_context);
|
|
17613
|
+
if (!func.runtime.widgets.supports_current_environment(definition)) {
|
|
17614
|
+
return report_error(`plugin ${plugin_name} is not available in the current environment`, true);
|
|
17615
|
+
}
|
|
17616
|
+
|
|
17617
|
+
const methods = definition?.methods || {};
|
|
16575
17618
|
if (methods && !methods[method]) {
|
|
16576
17619
|
return report_error('method not found');
|
|
16577
17620
|
}
|
|
@@ -16632,7 +17675,13 @@ func.runtime.widgets.render_node = async function (options) {
|
|
|
16632
17675
|
job_id: options.jobNoP,
|
|
16633
17676
|
});
|
|
16634
17677
|
|
|
16635
|
-
const params = func.runtime.widgets.build_params(
|
|
17678
|
+
const params = func.runtime.widgets.build_params(
|
|
17679
|
+
widget_context,
|
|
17680
|
+
func.runtime.ui.get_first_node($div),
|
|
17681
|
+
func.runtime.ui.get_data($div),
|
|
17682
|
+
plugin_setup_ret.data,
|
|
17683
|
+
api_utils,
|
|
17684
|
+
);
|
|
16636
17685
|
const fx = await func.runtime.widgets.get_resource(widget_context, 'runtime.mjs');
|
|
16637
17686
|
|
|
16638
17687
|
await func.runtime.widgets.load_runtime_css(widget_context);
|
|
@@ -16656,9 +17705,306 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16656
17705
|
|
|
16657
17706
|
// Browser-only special node renderers live here so the core render tree can stay focused.
|
|
16658
17707
|
|
|
17708
|
+
const normalize_runtime_tag_name = function (tag_name) {
|
|
17709
|
+
return `${tag_name || ''}`.trim().toLowerCase();
|
|
17710
|
+
};
|
|
17711
|
+
|
|
17712
|
+
const get_runtime_node_attributes = function (nodeP) {
|
|
17713
|
+
if (!nodeP?.attributes || typeof nodeP.attributes !== 'object') {
|
|
17714
|
+
return {};
|
|
17715
|
+
}
|
|
17716
|
+
|
|
17717
|
+
return nodeP.attributes;
|
|
17718
|
+
};
|
|
17719
|
+
|
|
17720
|
+
const get_runtime_node_content = function (nodeP) {
|
|
17721
|
+
if (typeof nodeP?.content === 'string') {
|
|
17722
|
+
return nodeP.content;
|
|
17723
|
+
}
|
|
17724
|
+
|
|
17725
|
+
if (typeof nodeP?.text === 'string') {
|
|
17726
|
+
return nodeP.text;
|
|
17727
|
+
}
|
|
17728
|
+
|
|
17729
|
+
if (!Array.isArray(nodeP?.children)) {
|
|
17730
|
+
return '';
|
|
17731
|
+
}
|
|
17732
|
+
|
|
17733
|
+
return nodeP.children
|
|
17734
|
+
.map(function (child) {
|
|
17735
|
+
if (typeof child === 'string') {
|
|
17736
|
+
return child;
|
|
17737
|
+
}
|
|
17738
|
+
if (typeof child?.content === 'string') {
|
|
17739
|
+
return child.content;
|
|
17740
|
+
}
|
|
17741
|
+
if (typeof child?.text === 'string') {
|
|
17742
|
+
return child.text;
|
|
17743
|
+
}
|
|
17744
|
+
return '';
|
|
17745
|
+
})
|
|
17746
|
+
.join('');
|
|
17747
|
+
};
|
|
17748
|
+
|
|
17749
|
+
const get_runtime_asset_key = function (options, tag_name) {
|
|
17750
|
+
const source_node = options.treeP || options.nodeP || {};
|
|
17751
|
+
const parts = [
|
|
17752
|
+
'xuda-html-asset',
|
|
17753
|
+
options.paramsP?.prog_id || '',
|
|
17754
|
+
tag_name,
|
|
17755
|
+
source_node.id || source_node.id_org || '',
|
|
17756
|
+
typeof options.keyP === 'undefined' || options.keyP === null ? '' : `${options.keyP}`,
|
|
17757
|
+
].filter(function (part) {
|
|
17758
|
+
return `${part || ''}`.trim() !== '';
|
|
17759
|
+
});
|
|
17760
|
+
|
|
17761
|
+
return parts.join(':');
|
|
17762
|
+
};
|
|
17763
|
+
|
|
17764
|
+
const get_runtime_asset_signature = function (attributes, content) {
|
|
17765
|
+
const normalized_attributes = {};
|
|
17766
|
+
const attr_keys = Object.keys(attributes || {}).sort();
|
|
17767
|
+
|
|
17768
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
17769
|
+
const key = attr_keys[index];
|
|
17770
|
+
normalized_attributes[key] = attributes[key];
|
|
17771
|
+
}
|
|
17772
|
+
|
|
17773
|
+
return JSON.stringify({
|
|
17774
|
+
attributes: normalized_attributes,
|
|
17775
|
+
content: `${content || ''}`,
|
|
17776
|
+
});
|
|
17777
|
+
};
|
|
17778
|
+
|
|
17779
|
+
const escape_runtime_asset_selector_value = function (value) {
|
|
17780
|
+
const win = func.runtime.platform.get_window?.();
|
|
17781
|
+
if (win?.CSS?.escape) {
|
|
17782
|
+
return win.CSS.escape(value);
|
|
17783
|
+
}
|
|
17784
|
+
|
|
17785
|
+
return `${value || ''}`.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
17786
|
+
};
|
|
17787
|
+
|
|
17788
|
+
const find_runtime_head_asset = function (head, tag_name, asset_key) {
|
|
17789
|
+
if (!head?.querySelector || !asset_key) {
|
|
17790
|
+
return null;
|
|
17791
|
+
}
|
|
17792
|
+
|
|
17793
|
+
return head.querySelector(`${tag_name}[data-xuda-asset-key="${escape_runtime_asset_selector_value(asset_key)}"]`);
|
|
17794
|
+
};
|
|
17795
|
+
|
|
17796
|
+
const find_runtime_head_asset_by_attr = function (head, tag_name, attr_name, attr_value) {
|
|
17797
|
+
if (!head?.querySelectorAll || !attr_name || !attr_value) {
|
|
17798
|
+
return null;
|
|
17799
|
+
}
|
|
17800
|
+
|
|
17801
|
+
const candidates = Array.from(head.querySelectorAll(tag_name));
|
|
17802
|
+
return (
|
|
17803
|
+
candidates.find(function (candidate) {
|
|
17804
|
+
return candidate.getAttribute(attr_name) === attr_value || candidate[attr_name] === attr_value;
|
|
17805
|
+
}) || null
|
|
17806
|
+
);
|
|
17807
|
+
};
|
|
17808
|
+
|
|
17809
|
+
const wait_for_runtime_asset_load = function (node) {
|
|
17810
|
+
if (!node?.addEventListener) {
|
|
17811
|
+
return Promise.resolve(node);
|
|
17812
|
+
}
|
|
17813
|
+
|
|
17814
|
+
if (node.getAttribute?.('data-xuda-loaded') === 'true') {
|
|
17815
|
+
return Promise.resolve(node);
|
|
17816
|
+
}
|
|
17817
|
+
|
|
17818
|
+
if (!node.getAttribute?.('data-xuda-asset-key')) {
|
|
17819
|
+
return Promise.resolve(node);
|
|
17820
|
+
}
|
|
17821
|
+
|
|
17822
|
+
const tag_name = normalize_runtime_tag_name(node.tagName);
|
|
17823
|
+
if (tag_name !== 'script' && !(tag_name === 'link' && normalize_runtime_tag_name(node.getAttribute?.('rel')) === 'stylesheet')) {
|
|
17824
|
+
return Promise.resolve(node);
|
|
17825
|
+
}
|
|
17826
|
+
|
|
17827
|
+
return new Promise(function (resolve) {
|
|
17828
|
+
const done = function () {
|
|
17829
|
+
node.setAttribute?.('data-xuda-loaded', 'true');
|
|
17830
|
+
resolve(node);
|
|
17831
|
+
};
|
|
17832
|
+
|
|
17833
|
+
node.addEventListener('load', done, { once: true });
|
|
17834
|
+
node.addEventListener('error', done, { once: true });
|
|
17835
|
+
});
|
|
17836
|
+
};
|
|
17837
|
+
|
|
17838
|
+
const remove_runtime_head_asset = function (node) {
|
|
17839
|
+
if (node?.parentNode?.removeChild) {
|
|
17840
|
+
node.parentNode.removeChild(node);
|
|
17841
|
+
}
|
|
17842
|
+
};
|
|
17843
|
+
|
|
17844
|
+
const apply_runtime_asset_metadata = function (node, asset_key, signature) {
|
|
17845
|
+
if (!node?.setAttribute) {
|
|
17846
|
+
return node;
|
|
17847
|
+
}
|
|
17848
|
+
|
|
17849
|
+
if (asset_key) {
|
|
17850
|
+
node.setAttribute('data-xuda-asset-key', asset_key);
|
|
17851
|
+
}
|
|
17852
|
+
node.setAttribute('data-xuda-asset-signature', signature);
|
|
17853
|
+
return node;
|
|
17854
|
+
};
|
|
17855
|
+
|
|
17856
|
+
const create_runtime_head_element = function (doc, tag_name, attributes, asset_key, signature) {
|
|
17857
|
+
const node = doc.createElement(tag_name);
|
|
17858
|
+
apply_runtime_asset_metadata(node, asset_key, signature);
|
|
17859
|
+
func.runtime.platform.apply_element_attributes(node, attributes);
|
|
17860
|
+
return node;
|
|
17861
|
+
};
|
|
17862
|
+
|
|
17863
|
+
const upsert_runtime_head_element = async function (options) {
|
|
17864
|
+
const doc = func.runtime.platform.get_document?.();
|
|
17865
|
+
const head = doc?.head;
|
|
17866
|
+
const tag_name = normalize_runtime_tag_name(options.tag_name);
|
|
17867
|
+
|
|
17868
|
+
if (!doc?.createElement || !head?.appendChild || !tag_name) {
|
|
17869
|
+
return null;
|
|
17870
|
+
}
|
|
17871
|
+
|
|
17872
|
+
const asset_key = options.asset_key || '';
|
|
17873
|
+
const signature = options.signature || '';
|
|
17874
|
+
const attributes = options.attributes || {};
|
|
17875
|
+
const content = typeof options.content === 'string' ? options.content : '';
|
|
17876
|
+
|
|
17877
|
+
const existing_by_key = find_runtime_head_asset(head, tag_name, asset_key);
|
|
17878
|
+
if (existing_by_key && existing_by_key.getAttribute('data-xuda-asset-signature') === signature) {
|
|
17879
|
+
return options.await_load ? await wait_for_runtime_asset_load(existing_by_key) : existing_by_key;
|
|
17880
|
+
}
|
|
17881
|
+
|
|
17882
|
+
if (existing_by_key) {
|
|
17883
|
+
remove_runtime_head_asset(existing_by_key);
|
|
17884
|
+
}
|
|
17885
|
+
|
|
17886
|
+
if (options.find_existing_attr?.name && options.find_existing_attr?.value) {
|
|
17887
|
+
const existing_by_attr = find_runtime_head_asset_by_attr(head, tag_name, options.find_existing_attr.name, options.find_existing_attr.value);
|
|
17888
|
+
if (existing_by_attr) {
|
|
17889
|
+
apply_runtime_asset_metadata(existing_by_attr, asset_key, signature);
|
|
17890
|
+
existing_by_attr.setAttribute?.('data-xuda-loaded', 'true');
|
|
17891
|
+
return existing_by_attr;
|
|
17892
|
+
}
|
|
17893
|
+
}
|
|
17894
|
+
|
|
17895
|
+
const node = create_runtime_head_element(doc, tag_name, attributes, asset_key, signature);
|
|
17896
|
+
|
|
17897
|
+
if (tag_name === 'script' && attributes.src && !Object.prototype.hasOwnProperty.call(attributes, 'async')) {
|
|
17898
|
+
const script_type = normalize_runtime_tag_name(attributes.type);
|
|
17899
|
+
if (script_type !== 'module') {
|
|
17900
|
+
node.async = false;
|
|
17901
|
+
}
|
|
17902
|
+
}
|
|
17903
|
+
|
|
17904
|
+
if (tag_name === 'style' || (tag_name === 'script' && !attributes.src)) {
|
|
17905
|
+
node.textContent = content;
|
|
17906
|
+
}
|
|
17907
|
+
|
|
17908
|
+
head.appendChild(node);
|
|
17909
|
+
|
|
17910
|
+
if (tag_name !== 'script' && tag_name !== 'link') {
|
|
17911
|
+
node.setAttribute('data-xuda-loaded', 'true');
|
|
17912
|
+
}
|
|
17913
|
+
|
|
17914
|
+
return options.await_load ? await wait_for_runtime_asset_load(node) : node;
|
|
17915
|
+
};
|
|
17916
|
+
|
|
17917
|
+
const render_runtime_html_asset = async function (options) {
|
|
17918
|
+
if (options.is_skeleton) {
|
|
17919
|
+
return options.$container;
|
|
17920
|
+
}
|
|
17921
|
+
|
|
17922
|
+
const nodeP = options.treeP || options.nodeP || {};
|
|
17923
|
+
const tag_name = normalize_runtime_tag_name(nodeP.tagName);
|
|
17924
|
+
const attributes = { ...get_runtime_node_attributes(nodeP) };
|
|
17925
|
+
const content = get_runtime_node_content(nodeP);
|
|
17926
|
+
const asset_key = get_runtime_asset_key(options, tag_name);
|
|
17927
|
+
const signature = get_runtime_asset_signature(attributes, content);
|
|
17928
|
+
|
|
17929
|
+
switch (tag_name) {
|
|
17930
|
+
case 'title':
|
|
17931
|
+
func.runtime.platform.set_title(content);
|
|
17932
|
+
return options.$container;
|
|
17933
|
+
case 'style':
|
|
17934
|
+
await upsert_runtime_head_element({
|
|
17935
|
+
tag_name,
|
|
17936
|
+
attributes,
|
|
17937
|
+
content,
|
|
17938
|
+
asset_key,
|
|
17939
|
+
signature,
|
|
17940
|
+
});
|
|
17941
|
+
return options.$container;
|
|
17942
|
+
case 'meta':
|
|
17943
|
+
if (!Object.keys(attributes).length) {
|
|
17944
|
+
return options.$container;
|
|
17945
|
+
}
|
|
17946
|
+
await upsert_runtime_head_element({
|
|
17947
|
+
tag_name,
|
|
17948
|
+
attributes,
|
|
17949
|
+
asset_key,
|
|
17950
|
+
signature,
|
|
17951
|
+
});
|
|
17952
|
+
return options.$container;
|
|
17953
|
+
case 'link': {
|
|
17954
|
+
const href = `${attributes.href || ''}`.trim();
|
|
17955
|
+
if (!href) {
|
|
17956
|
+
return options.$container;
|
|
17957
|
+
}
|
|
17958
|
+
await upsert_runtime_head_element({
|
|
17959
|
+
tag_name,
|
|
17960
|
+
attributes,
|
|
17961
|
+
asset_key,
|
|
17962
|
+
signature,
|
|
17963
|
+
find_existing_attr: {
|
|
17964
|
+
name: 'href',
|
|
17965
|
+
value: href,
|
|
17966
|
+
},
|
|
17967
|
+
await_load: normalize_runtime_tag_name(attributes.rel) === 'stylesheet',
|
|
17968
|
+
});
|
|
17969
|
+
return options.$container;
|
|
17970
|
+
}
|
|
17971
|
+
case 'script': {
|
|
17972
|
+
const src = `${attributes.src || ''}`.trim();
|
|
17973
|
+
if (!src && !content.trim()) {
|
|
17974
|
+
return options.$container;
|
|
17975
|
+
}
|
|
17976
|
+
await upsert_runtime_head_element({
|
|
17977
|
+
tag_name,
|
|
17978
|
+
attributes,
|
|
17979
|
+
content,
|
|
17980
|
+
asset_key,
|
|
17981
|
+
signature,
|
|
17982
|
+
find_existing_attr: src
|
|
17983
|
+
? {
|
|
17984
|
+
name: 'src',
|
|
17985
|
+
value: src,
|
|
17986
|
+
}
|
|
17987
|
+
: null,
|
|
17988
|
+
await_load: !!src,
|
|
17989
|
+
});
|
|
17990
|
+
return options.$container;
|
|
17991
|
+
}
|
|
17992
|
+
default:
|
|
17993
|
+
return null;
|
|
17994
|
+
}
|
|
17995
|
+
};
|
|
17996
|
+
|
|
16659
17997
|
func.runtime.render.render_special_node = async function (options) {
|
|
16660
|
-
|
|
16661
|
-
|
|
17998
|
+
const treeP = options.treeP || null;
|
|
17999
|
+
const nodeP = options.nodeP || func.runtime.render.get_tree_source_node(treeP);
|
|
18000
|
+
const render_tag_name = treeP?.tagName || nodeP?.tagName;
|
|
18001
|
+
const normalized_render_tag_name = normalize_runtime_tag_name(render_tag_name);
|
|
18002
|
+
const is_native_html_asset = ['title', 'style', 'meta', 'link', 'script'].includes(normalized_render_tag_name);
|
|
18003
|
+
|
|
18004
|
+
if (!is_native_html_asset && treeP?.content && nodeP?.attributes) {
|
|
18005
|
+
nodeP.attributes['xu-content'] = treeP.content;
|
|
18006
|
+
} else if (!is_native_html_asset && nodeP?.content && nodeP.attributes) {
|
|
18007
|
+
nodeP.attributes['xu-content'] = nodeP.content;
|
|
16662
18008
|
}
|
|
16663
18009
|
|
|
16664
18010
|
const renderers = {
|
|
@@ -16668,6 +18014,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16668
18014
|
SESSION_ID: options.SESSION_ID,
|
|
16669
18015
|
$container: options.$container,
|
|
16670
18016
|
$root_container: options.$root_container,
|
|
18017
|
+
treeP,
|
|
16671
18018
|
nodeP: options.nodeP,
|
|
16672
18019
|
parent_infoP: options.parent_infoP,
|
|
16673
18020
|
paramsP: options.paramsP,
|
|
@@ -16684,6 +18031,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16684
18031
|
SESSION_ID: options.SESSION_ID,
|
|
16685
18032
|
$container: options.$container,
|
|
16686
18033
|
$root_container: options.$root_container,
|
|
18034
|
+
treeP,
|
|
16687
18035
|
nodeP: options.nodeP,
|
|
16688
18036
|
parent_infoP: options.parent_infoP,
|
|
16689
18037
|
paramsP: options.paramsP,
|
|
@@ -16703,6 +18051,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16703
18051
|
SESSION_ID: options.SESSION_ID,
|
|
16704
18052
|
$container: options.$container,
|
|
16705
18053
|
$root_container: options.$root_container,
|
|
18054
|
+
treeP,
|
|
16706
18055
|
nodeP: options.nodeP,
|
|
16707
18056
|
parent_infoP: options.parent_infoP,
|
|
16708
18057
|
paramsP: options.paramsP,
|
|
@@ -16719,6 +18068,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16719
18068
|
SESSION_ID: options.SESSION_ID,
|
|
16720
18069
|
$container: options.$container,
|
|
16721
18070
|
$root_container: options.$root_container,
|
|
18071
|
+
treeP,
|
|
16722
18072
|
nodeP: options.nodeP,
|
|
16723
18073
|
parent_infoP: options.parent_infoP,
|
|
16724
18074
|
paramsP: options.paramsP,
|
|
@@ -16730,9 +18080,24 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16730
18080
|
refreshed_ds: options.refreshed_ds,
|
|
16731
18081
|
});
|
|
16732
18082
|
},
|
|
18083
|
+
title: async function () {
|
|
18084
|
+
return await render_runtime_html_asset(options);
|
|
18085
|
+
},
|
|
18086
|
+
style: async function () {
|
|
18087
|
+
return await render_runtime_html_asset(options);
|
|
18088
|
+
},
|
|
18089
|
+
meta: async function () {
|
|
18090
|
+
return await render_runtime_html_asset(options);
|
|
18091
|
+
},
|
|
18092
|
+
link: async function () {
|
|
18093
|
+
return await render_runtime_html_asset(options);
|
|
18094
|
+
},
|
|
18095
|
+
script: async function () {
|
|
18096
|
+
return await render_runtime_html_asset(options);
|
|
18097
|
+
},
|
|
16733
18098
|
};
|
|
16734
18099
|
|
|
16735
|
-
const renderer = renderers[
|
|
18100
|
+
const renderer = renderers[normalized_render_tag_name];
|
|
16736
18101
|
if (!renderer) {
|
|
16737
18102
|
return { handled: false };
|
|
16738
18103
|
}
|
|
@@ -16846,8 +18211,9 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16846
18211
|
// Browser-only render tree entrypoints live here so draw/cache helpers can stay focused.
|
|
16847
18212
|
|
|
16848
18213
|
func.runtime.render.create_tree_runtime = function (options) {
|
|
18214
|
+
const render_node = options.nodeP || func.runtime.render.get_tree_source_node(options.treeP);
|
|
16849
18215
|
const render_context = func.runtime.render.get_screen_context(options.SESSION_ID, options.$container, options.paramsP, options.is_skeleton);
|
|
16850
|
-
const prop = func.runtime.render.get_node_attributes(options.
|
|
18216
|
+
const prop = func.runtime.render.get_node_attributes(options.treeP || render_node);
|
|
16851
18217
|
const is_mobile = render_context.is_mobile ? true : false;
|
|
16852
18218
|
const hover_handlers = func.runtime.render.create_hover_handlers({
|
|
16853
18219
|
SESSION_ID: options.SESSION_ID,
|
|
@@ -16862,13 +18228,22 @@ func.runtime.render.create_tree_runtime = function (options) {
|
|
|
16862
18228
|
return await func.runtime.ui.close_modal_session(options.SESSION_ID, modal_id);
|
|
16863
18229
|
};
|
|
16864
18230
|
const iterate_child = async function ($divP, nodeP, parent_infoP, $root_container, before_record_function) {
|
|
18231
|
+
const child_tree = await func.runtime.render.ensure_tree_node({
|
|
18232
|
+
SESSION_ID: options.SESSION_ID,
|
|
18233
|
+
nodeP: nodeP || options.treeP || render_node,
|
|
18234
|
+
parent_infoP,
|
|
18235
|
+
paramsP: options.paramsP,
|
|
18236
|
+
keyP: options.keyP,
|
|
18237
|
+
parent_nodeP: render_node,
|
|
18238
|
+
pathP: options.treeP?.meta?.path || [],
|
|
18239
|
+
});
|
|
16865
18240
|
return await func.runtime.render.iterate_children({
|
|
16866
18241
|
$divP,
|
|
16867
|
-
nodeP,
|
|
18242
|
+
nodeP: child_tree,
|
|
16868
18243
|
is_mobile,
|
|
16869
18244
|
before_record_function,
|
|
16870
18245
|
render_child: async function (key, child) {
|
|
16871
|
-
await options.render_child($divP, child, parent_infoP, key,
|
|
18246
|
+
await options.render_child($divP, child, parent_infoP, key, render_node, $root_container);
|
|
16872
18247
|
},
|
|
16873
18248
|
});
|
|
16874
18249
|
};
|
|
@@ -16898,7 +18273,7 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16898
18273
|
check_existP: options.check_existP,
|
|
16899
18274
|
$root_container: options.$root_container,
|
|
16900
18275
|
prop: options.prop,
|
|
16901
|
-
element: options.nodeP.tagName,
|
|
18276
|
+
element: options.treeP?.tagName || options.nodeP.tagName,
|
|
16902
18277
|
hover_handlers: options.hover_handlers,
|
|
16903
18278
|
include_hover_click: options.include_hover_click,
|
|
16904
18279
|
iterate_child: options.iterate_child,
|
|
@@ -16921,21 +18296,33 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16921
18296
|
nodeP: options.nodeP,
|
|
16922
18297
|
});
|
|
16923
18298
|
};
|
|
16924
|
-
func.runtime.render.
|
|
16925
|
-
if (!
|
|
16926
|
-
const
|
|
16927
|
-
func.runtime?.perf?.
|
|
18299
|
+
func.runtime.render.render_tree = async function (treeP, renderer_context) {
|
|
18300
|
+
if (!treeP) return;
|
|
18301
|
+
const nodeP = func.runtime.render.get_tree_source_node(treeP);
|
|
18302
|
+
const perf_end = func.runtime?.perf?.start?.(renderer_context.SESSION_ID, 'render_ui_tree');
|
|
18303
|
+
func.runtime?.perf?.increment_map?.(renderer_context.SESSION_ID, 'render_node_counts', treeP.id || nodeP?.id || nodeP?.id_org || treeP.tagName || 'unknown');
|
|
16928
18304
|
try {
|
|
16929
18305
|
const tree_runtime = func.runtime.render.create_tree_runtime({
|
|
16930
|
-
SESSION_ID,
|
|
16931
|
-
$container,
|
|
18306
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18307
|
+
$container: renderer_context.$container,
|
|
18308
|
+
treeP,
|
|
16932
18309
|
nodeP,
|
|
16933
|
-
parent_infoP,
|
|
16934
|
-
paramsP,
|
|
16935
|
-
jobNoP,
|
|
16936
|
-
is_skeleton,
|
|
18310
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18311
|
+
paramsP: renderer_context.paramsP,
|
|
18312
|
+
jobNoP: renderer_context.jobNoP,
|
|
18313
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18314
|
+
keyP: renderer_context.keyP,
|
|
16937
18315
|
render_child: async function ($divP, child, parent_infoP, key, parentNodeP, rootContainerP) {
|
|
16938
|
-
await func.runtime.render.
|
|
18316
|
+
await func.runtime.render.render_tree(child, {
|
|
18317
|
+
...renderer_context,
|
|
18318
|
+
$container: $divP,
|
|
18319
|
+
parent_infoP,
|
|
18320
|
+
keyP: key,
|
|
18321
|
+
refreshed_ds: null,
|
|
18322
|
+
parent_nodeP: parentNodeP,
|
|
18323
|
+
check_existP: null,
|
|
18324
|
+
$root_container: rootContainerP,
|
|
18325
|
+
});
|
|
16939
18326
|
},
|
|
16940
18327
|
});
|
|
16941
18328
|
const render_context = tree_runtime.render_context;
|
|
@@ -16947,23 +18334,24 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16947
18334
|
const iterate_child = tree_runtime.iterate_child;
|
|
16948
18335
|
|
|
16949
18336
|
func.runtime.render.log_tree_debug({
|
|
16950
|
-
SESSION_ID,
|
|
16951
|
-
paramsP,
|
|
18337
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18338
|
+
paramsP: renderer_context.paramsP,
|
|
16952
18339
|
nodeP,
|
|
16953
18340
|
_ds,
|
|
16954
18341
|
});
|
|
16955
18342
|
const special_render = await func.runtime.render.render_special_node({
|
|
16956
|
-
SESSION_ID,
|
|
16957
|
-
$container,
|
|
16958
|
-
$root_container,
|
|
18343
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18344
|
+
$container: renderer_context.$container,
|
|
18345
|
+
$root_container: renderer_context.$root_container,
|
|
18346
|
+
treeP,
|
|
16959
18347
|
nodeP,
|
|
16960
|
-
parent_infoP,
|
|
16961
|
-
paramsP,
|
|
16962
|
-
jobNoP,
|
|
16963
|
-
is_skeleton,
|
|
16964
|
-
keyP,
|
|
16965
|
-
refreshed_ds,
|
|
16966
|
-
parent_nodeP,
|
|
18348
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18349
|
+
paramsP: renderer_context.paramsP,
|
|
18350
|
+
jobNoP: renderer_context.jobNoP,
|
|
18351
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18352
|
+
keyP: renderer_context.keyP,
|
|
18353
|
+
refreshed_ds: renderer_context.refreshed_ds,
|
|
18354
|
+
parent_nodeP: renderer_context.parent_nodeP,
|
|
16967
18355
|
prop,
|
|
16968
18356
|
render_context,
|
|
16969
18357
|
hover_handlers,
|
|
@@ -16971,22 +18359,23 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16971
18359
|
close_modal,
|
|
16972
18360
|
});
|
|
16973
18361
|
if (special_render.handled) {
|
|
16974
|
-
func.runtime?.perf?.increment?.(SESSION_ID, 'render_special_node_hits');
|
|
18362
|
+
func.runtime?.perf?.increment?.(renderer_context.SESSION_ID, 'render_special_node_hits');
|
|
16975
18363
|
return special_render.result;
|
|
16976
18364
|
}
|
|
16977
18365
|
return await func.runtime.render.draw_node({
|
|
16978
|
-
SESSION_ID,
|
|
16979
|
-
$container,
|
|
16980
|
-
$root_container,
|
|
18366
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18367
|
+
$container: renderer_context.$container,
|
|
18368
|
+
$root_container: renderer_context.$root_container,
|
|
18369
|
+
treeP,
|
|
16981
18370
|
nodeP,
|
|
16982
|
-
parent_infoP,
|
|
16983
|
-
paramsP,
|
|
16984
|
-
jobNoP,
|
|
16985
|
-
is_skeleton,
|
|
16986
|
-
keyP,
|
|
16987
|
-
refreshed_ds,
|
|
16988
|
-
parent_nodeP,
|
|
16989
|
-
check_existP,
|
|
18371
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18372
|
+
paramsP: renderer_context.paramsP,
|
|
18373
|
+
jobNoP: renderer_context.jobNoP,
|
|
18374
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18375
|
+
keyP: renderer_context.keyP,
|
|
18376
|
+
refreshed_ds: renderer_context.refreshed_ds,
|
|
18377
|
+
parent_nodeP: renderer_context.parent_nodeP,
|
|
18378
|
+
check_existP: renderer_context.check_existP,
|
|
16990
18379
|
prop,
|
|
16991
18380
|
hover_handlers,
|
|
16992
18381
|
include_hover_click,
|
|
@@ -16995,6 +18384,31 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16995
18384
|
} finally {
|
|
16996
18385
|
perf_end?.();
|
|
16997
18386
|
}
|
|
18387
|
+
};
|
|
18388
|
+
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) {
|
|
18389
|
+
if (!nodeP) return;
|
|
18390
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
18391
|
+
SESSION_ID,
|
|
18392
|
+
nodeP,
|
|
18393
|
+
parent_infoP,
|
|
18394
|
+
paramsP,
|
|
18395
|
+
keyP,
|
|
18396
|
+
parent_nodeP,
|
|
18397
|
+
});
|
|
18398
|
+
|
|
18399
|
+
return await func.runtime.render.render_tree(treeP, {
|
|
18400
|
+
SESSION_ID,
|
|
18401
|
+
$container,
|
|
18402
|
+
parent_infoP,
|
|
18403
|
+
paramsP,
|
|
18404
|
+
jobNoP,
|
|
18405
|
+
is_skeleton,
|
|
18406
|
+
keyP,
|
|
18407
|
+
refreshed_ds,
|
|
18408
|
+
parent_nodeP,
|
|
18409
|
+
check_existP,
|
|
18410
|
+
$root_container,
|
|
18411
|
+
});
|
|
16998
18412
|
};
|
|
16999
18413
|
func.runtime = func.runtime || {};
|
|
17000
18414
|
func.runtime.ui = func.runtime.ui || {};
|
|
@@ -17662,7 +19076,7 @@ func.runtime.render.handle_xu_ref = async function (options) {
|
|
|
17662
19076
|
func.runtime.render.handle_xu_bind = async function (options) {
|
|
17663
19077
|
if (options.is_skeleton) return {};
|
|
17664
19078
|
|
|
17665
|
-
const $elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(options.$elm) :
|
|
19079
|
+
const $elm = func.runtime?.ui?.get_preferred_live_element ? func.runtime.ui.get_preferred_live_element(options.$elm) : options.$elm;
|
|
17666
19080
|
const elm_data = func.runtime.ui.get_data($elm);
|
|
17667
19081
|
const xuData = elm_data?.xuData;
|
|
17668
19082
|
const bind_expression =
|
|
@@ -18518,6 +19932,7 @@ func.runtime.render.handle_xu_panel_program = async function (options) {
|
|
|
18518
19932
|
parent_infoP: options.parent_infoP,
|
|
18519
19933
|
jobNoP: options.jobNoP,
|
|
18520
19934
|
keyP: options.keyP,
|
|
19935
|
+
treeP: options.treeP,
|
|
18521
19936
|
parent_nodeP: options.parent_nodeP,
|
|
18522
19937
|
prop: options.nodeP.attributes,
|
|
18523
19938
|
$appendToP: $wrapper,
|
|
@@ -22531,6 +23946,12 @@ function xuda(...args) {
|
|
|
22531
23946
|
if (typeof opt !== 'object') {
|
|
22532
23947
|
return console.error('Xuda Error - opt argument is not an object');
|
|
22533
23948
|
}
|
|
23949
|
+
|
|
23950
|
+
if (!opt.ssr_payload && func.runtime.platform.get_window()?.__XUDA_SSR__) {
|
|
23951
|
+
opt.ssr_payload = func.runtime.platform.get_window().__XUDA_SSR__;
|
|
23952
|
+
}
|
|
23953
|
+
func.runtime.render.apply_runtime_bootstrap_defaults(opt);
|
|
23954
|
+
|
|
22534
23955
|
glb.URL_PARAMS = func.common.getJsonFromUrl(platform.get_url_href());
|
|
22535
23956
|
|
|
22536
23957
|
glb.worker_type = 'Worker';
|