@xuda.io/runtime-bundle 1.0.1436 → 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/xuda-runtime-bundle.js +1464 -69
- package/js/xuda-runtime-bundle.min.js +3 -3
- package/js/xuda-runtime-slim.js +1464 -69
- package/js/xuda-runtime-slim.min.es.js +1464 -69
- package/js/xuda-runtime-slim.min.js +3 -3
- package/js/xuda-server-bundle.min.mjs +1 -1
- package/js/xuda-server-bundle.mjs +901 -6
- package/js/xuda-worker-bundle.js +901 -6
- package/js/xuda-worker-bundle.min.js +1 -1
- package/js/xuda_common-bundle.js +216 -6
- package/js/xuda_common-bundle.min.js +1 -1
- package/package.json +1 -1
|
@@ -1705,7 +1705,30 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
1705
1705
|
};
|
|
1706
1706
|
|
|
1707
1707
|
// ── Platform helpers for DOM-independent resource loading ──
|
|
1708
|
-
func.runtime.platform.
|
|
1708
|
+
func.runtime.platform.apply_element_attributes = function (node, attributes, excluded_keys = []) {
|
|
1709
|
+
if (!node?.setAttribute || !attributes) {
|
|
1710
|
+
return node;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
const excluded = new Set(excluded_keys || []);
|
|
1714
|
+
const attr_keys = Object.keys(attributes);
|
|
1715
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
1716
|
+
const key = attr_keys[index];
|
|
1717
|
+
if (!key || excluded.has(key)) {
|
|
1718
|
+
continue;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
const value = attributes[key];
|
|
1722
|
+
if (value === false || typeof value === 'undefined') {
|
|
1723
|
+
continue;
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
node.setAttribute(key, value === null ? '' : `${value}`);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
return node;
|
|
1730
|
+
};
|
|
1731
|
+
func.runtime.platform.load_script = function (url, type, callback, attributes) {
|
|
1709
1732
|
const doc = func.runtime.platform.get_document();
|
|
1710
1733
|
if (!doc?.createElement || !doc?.head?.appendChild) {
|
|
1711
1734
|
if (callback) {
|
|
@@ -1713,19 +1736,63 @@ func.runtime.platform.load_script = function (url, type, callback) {
|
|
|
1713
1736
|
}
|
|
1714
1737
|
return;
|
|
1715
1738
|
}
|
|
1739
|
+
const find_existing_script = function () {
|
|
1740
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
1741
|
+
const scripts = doc.querySelectorAll ? Array.from(doc.querySelectorAll('script')) : [];
|
|
1742
|
+
return scripts.find(function (script) {
|
|
1743
|
+
if (asset_key && script.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
1744
|
+
return true;
|
|
1745
|
+
}
|
|
1746
|
+
return !!(url && script.getAttribute('src') === url);
|
|
1747
|
+
}) || null;
|
|
1748
|
+
};
|
|
1749
|
+
|
|
1750
|
+
const existing_script = find_existing_script();
|
|
1751
|
+
if (existing_script) {
|
|
1752
|
+
if (callback) {
|
|
1753
|
+
if (existing_script.getAttribute('data-xuda-loaded') === 'true' || !url) {
|
|
1754
|
+
callback();
|
|
1755
|
+
} else {
|
|
1756
|
+
existing_script.addEventListener('load', callback, { once: true });
|
|
1757
|
+
existing_script.addEventListener('error', callback, { once: true });
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return existing_script;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1716
1763
|
const script = doc.createElement('script');
|
|
1717
1764
|
script.src = url;
|
|
1718
1765
|
if (type) script.type = type;
|
|
1719
|
-
script
|
|
1766
|
+
func.runtime.platform.apply_element_attributes(script, attributes, ['src', 'type']);
|
|
1767
|
+
script.onload = function () {
|
|
1768
|
+
script.setAttribute('data-xuda-loaded', 'true');
|
|
1769
|
+
if (callback) {
|
|
1770
|
+
callback();
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
script.onerror = function () {
|
|
1774
|
+
if (callback) {
|
|
1775
|
+
callback();
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1720
1778
|
doc.head.appendChild(script);
|
|
1779
|
+
return script;
|
|
1721
1780
|
};
|
|
1722
|
-
func.runtime.platform.load_css = function (href) {
|
|
1781
|
+
func.runtime.platform.load_css = function (href, attributes) {
|
|
1723
1782
|
const doc = func.runtime.platform.get_document();
|
|
1724
1783
|
if (!doc?.createElement || !doc?.head) {
|
|
1725
1784
|
return;
|
|
1726
1785
|
}
|
|
1727
1786
|
try {
|
|
1728
|
-
|
|
1787
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
1788
|
+
const existing_links = doc.querySelectorAll ? Array.from(doc.querySelectorAll('link')) : [];
|
|
1789
|
+
const existing = existing_links.find(function (link) {
|
|
1790
|
+
if (asset_key && link.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
1791
|
+
return true;
|
|
1792
|
+
}
|
|
1793
|
+
return !!(href && link.getAttribute('href') === href);
|
|
1794
|
+
});
|
|
1795
|
+
if (existing) return existing;
|
|
1729
1796
|
} catch (err) {
|
|
1730
1797
|
return;
|
|
1731
1798
|
}
|
|
@@ -1733,7 +1800,9 @@ func.runtime.platform.load_css = function (href) {
|
|
|
1733
1800
|
link.rel = 'stylesheet';
|
|
1734
1801
|
link.type = 'text/css';
|
|
1735
1802
|
link.href = href;
|
|
1803
|
+
func.runtime.platform.apply_element_attributes(link, attributes, ['href']);
|
|
1736
1804
|
doc.head.insertBefore(link, doc.head.firstChild);
|
|
1805
|
+
return link;
|
|
1737
1806
|
};
|
|
1738
1807
|
func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
1739
1808
|
const doc = func.runtime.platform.get_document();
|
|
@@ -2024,6 +2093,147 @@ func.runtime.workers.delete_promise = function (SESSION_ID, worker_id, promise_q
|
|
|
2024
2093
|
delete registry_entry.promise_queue[promise_queue_id];
|
|
2025
2094
|
return true;
|
|
2026
2095
|
};
|
|
2096
|
+
func.runtime.render.clone_runtime_options = function (value) {
|
|
2097
|
+
if (typeof structuredClone === 'function') {
|
|
2098
|
+
try {
|
|
2099
|
+
return structuredClone(value);
|
|
2100
|
+
} catch (_) {}
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
if (Array.isArray(value)) {
|
|
2104
|
+
return value.map(function (item) {
|
|
2105
|
+
return func.runtime.render.clone_runtime_options(item);
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
if (value && typeof value === 'object') {
|
|
2110
|
+
const cloned = {};
|
|
2111
|
+
const keys = Object.keys(value);
|
|
2112
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2113
|
+
const key = keys[index];
|
|
2114
|
+
cloned[key] = func.runtime.render.clone_runtime_options(value[key]);
|
|
2115
|
+
}
|
|
2116
|
+
return cloned;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
return value;
|
|
2120
|
+
};
|
|
2121
|
+
func.runtime.render.normalize_runtime_bootstrap = function (raw_options = {}) {
|
|
2122
|
+
const options = raw_options || {};
|
|
2123
|
+
let app_computing_mode = options.app_computing_mode || '';
|
|
2124
|
+
let app_render_mode = options.app_render_mode || '';
|
|
2125
|
+
let app_client_activation = options.app_client_activation || '';
|
|
2126
|
+
let ssr_payload = options.ssr_payload || null;
|
|
2127
|
+
|
|
2128
|
+
if (typeof ssr_payload === 'string') {
|
|
2129
|
+
try {
|
|
2130
|
+
ssr_payload = JSON.parse(ssr_payload);
|
|
2131
|
+
} catch (_) {
|
|
2132
|
+
ssr_payload = null;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
2137
|
+
ssr_payload = func.runtime.render.clone_runtime_options(ssr_payload);
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
if (!app_computing_mode) {
|
|
2141
|
+
if (app_render_mode === 'ssr_first_page' || app_render_mode === 'ssr_full') {
|
|
2142
|
+
app_computing_mode = 'server';
|
|
2143
|
+
} else {
|
|
2144
|
+
app_computing_mode = 'main';
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
switch (app_computing_mode) {
|
|
2149
|
+
case 'main':
|
|
2150
|
+
app_render_mode = 'csr';
|
|
2151
|
+
app_client_activation = 'none';
|
|
2152
|
+
break;
|
|
2153
|
+
|
|
2154
|
+
case 'worker':
|
|
2155
|
+
app_render_mode = 'csr';
|
|
2156
|
+
app_client_activation = 'none';
|
|
2157
|
+
break;
|
|
2158
|
+
|
|
2159
|
+
default:
|
|
2160
|
+
app_computing_mode = 'server';
|
|
2161
|
+
if (app_render_mode !== 'ssr_full') {
|
|
2162
|
+
app_render_mode = 'ssr_first_page';
|
|
2163
|
+
}
|
|
2164
|
+
app_client_activation = app_render_mode === 'ssr_full' ? 'hydrate' : 'takeover';
|
|
2165
|
+
break;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
2169
|
+
if (!ssr_payload.app_render_mode) {
|
|
2170
|
+
ssr_payload.app_render_mode = app_render_mode;
|
|
2171
|
+
}
|
|
2172
|
+
if (!ssr_payload.app_client_activation) {
|
|
2173
|
+
ssr_payload.app_client_activation = app_client_activation;
|
|
2174
|
+
}
|
|
2175
|
+
if (!ssr_payload.app_computing_mode) {
|
|
2176
|
+
ssr_payload.app_computing_mode = app_computing_mode;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
return {
|
|
2181
|
+
app_computing_mode,
|
|
2182
|
+
app_render_mode,
|
|
2183
|
+
app_client_activation,
|
|
2184
|
+
ssr_payload,
|
|
2185
|
+
};
|
|
2186
|
+
};
|
|
2187
|
+
func.runtime.render.apply_runtime_bootstrap_defaults = function (target = {}) {
|
|
2188
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target);
|
|
2189
|
+
target.app_computing_mode = normalized.app_computing_mode;
|
|
2190
|
+
target.app_render_mode = normalized.app_render_mode;
|
|
2191
|
+
target.app_client_activation = normalized.app_client_activation;
|
|
2192
|
+
target.ssr_payload = normalized.ssr_payload;
|
|
2193
|
+
return normalized;
|
|
2194
|
+
};
|
|
2195
|
+
func.runtime.render.is_server_render_mode = function (target = {}) {
|
|
2196
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2197
|
+
return normalized.app_computing_mode === 'server' && normalized.app_render_mode !== 'csr';
|
|
2198
|
+
};
|
|
2199
|
+
func.runtime.render.is_takeover_mode = function (target = {}) {
|
|
2200
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2201
|
+
return normalized.app_client_activation === 'takeover';
|
|
2202
|
+
};
|
|
2203
|
+
func.runtime.render.is_hydration_mode = function (target = {}) {
|
|
2204
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
2205
|
+
return normalized.app_client_activation === 'hydrate';
|
|
2206
|
+
};
|
|
2207
|
+
func.runtime.render.get_ssr_payload = function (target = {}) {
|
|
2208
|
+
if (target?.opt?.ssr_payload) {
|
|
2209
|
+
return target.opt.ssr_payload;
|
|
2210
|
+
}
|
|
2211
|
+
if (target?.ssr_payload) {
|
|
2212
|
+
return target.ssr_payload;
|
|
2213
|
+
}
|
|
2214
|
+
const win = func.runtime.platform.get_window();
|
|
2215
|
+
return win?.__XUDA_SSR__ || null;
|
|
2216
|
+
};
|
|
2217
|
+
func.runtime.render.should_use_ssr_payload = function (SESSION_ID, paramsP) {
|
|
2218
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
2219
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
2220
|
+
if (!payload || payload._consumed) {
|
|
2221
|
+
return false;
|
|
2222
|
+
}
|
|
2223
|
+
if (paramsP?.prog_id && payload.prog_id && payload.prog_id !== paramsP.prog_id) {
|
|
2224
|
+
return false;
|
|
2225
|
+
}
|
|
2226
|
+
return true;
|
|
2227
|
+
};
|
|
2228
|
+
func.runtime.render.mark_ssr_payload_consumed = function (SESSION_ID) {
|
|
2229
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
2230
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
2231
|
+
if (!payload || typeof payload !== 'object') {
|
|
2232
|
+
return false;
|
|
2233
|
+
}
|
|
2234
|
+
payload._consumed = true;
|
|
2235
|
+
return true;
|
|
2236
|
+
};
|
|
2027
2237
|
func.runtime.render.get_root_data_system = function (SESSION_ID) {
|
|
2028
2238
|
return SESSION_OBJ[SESSION_ID]?.DS_GLB?.[0]?.data_system || null;
|
|
2029
2239
|
};
|
|
@@ -2427,10 +2637,10 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
2427
2637
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
2428
2638
|
break;
|
|
2429
2639
|
case 'css':
|
|
2430
|
-
|
|
2640
|
+
func.runtime.platform.load_css(normalized_resource.src);
|
|
2431
2641
|
break;
|
|
2432
2642
|
case 'module':
|
|
2433
|
-
func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2643
|
+
await func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2434
2644
|
break;
|
|
2435
2645
|
default:
|
|
2436
2646
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
@@ -3743,30 +3953,715 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
|
|
|
3743
3953
|
// // The .toString(36) method handles the conversion to an alphanumeric representation (0-9, a-z).
|
|
3744
3954
|
// const base36Hash = bigInt.toString(36);
|
|
3745
3955
|
|
|
3746
|
-
// // 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
|
|
3747
|
-
// // For a 64-bit integer, the Base36 representation will be about 13 characters long,
|
|
3748
|
-
// // so slicing is a reliable way to get a fixed length.
|
|
3749
|
-
// const shortHash = base36Hash.slice(0, 10);
|
|
3956
|
+
// // 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
|
|
3957
|
+
// // For a 64-bit integer, the Base36 representation will be about 13 characters long,
|
|
3958
|
+
// // so slicing is a reliable way to get a fixed length.
|
|
3959
|
+
// const shortHash = base36Hash.slice(0, 10);
|
|
3960
|
+
|
|
3961
|
+
// // 5. Pad the start in the unlikely case the hash is shorter than 10 characters.
|
|
3962
|
+
// // This ensures the output is always exactly 10 characters long.
|
|
3963
|
+
// return shortHash.padStart(10, '0');
|
|
3964
|
+
// };
|
|
3965
|
+
|
|
3966
|
+
func.common.fastHash = function (inputString) {
|
|
3967
|
+
let hash = 0x811c9dc5; // FNV offset basis
|
|
3968
|
+
|
|
3969
|
+
for (let i = 0; i < inputString.length; i++) {
|
|
3970
|
+
hash ^= inputString.charCodeAt(i);
|
|
3971
|
+
// FNV prime multiplication with 32-bit overflow
|
|
3972
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
// Convert to base36 and pad to 10 characters
|
|
3976
|
+
return ((hash >>> 0).toString(36) + '0000000000').slice(0, 10);
|
|
3977
|
+
};
|
|
3978
|
+
|
|
3979
|
+
glb.new_xu_render = false;
|
|
3980
|
+
func.runtime = func.runtime || {};
|
|
3981
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
3982
|
+
func.runtime.render = func.runtime.render || {};
|
|
3983
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
3984
|
+
|
|
3985
|
+
// Shared render-tree contract helpers live here so browser and headless runtimes can resolve the same UI structure.
|
|
3986
|
+
|
|
3987
|
+
func.runtime.render.TREE_CONTRACT_VERSION = func.runtime.render.TREE_CONTRACT_VERSION || 'xuda.render_tree.v1';
|
|
3988
|
+
func.runtime.render._tree_widget_capability_cache = func.runtime.render._tree_widget_capability_cache || {};
|
|
3989
|
+
|
|
3990
|
+
func.runtime.render.safe_clone_tree_value = function (value) {
|
|
3991
|
+
if (typeof structuredClone === 'function') {
|
|
3992
|
+
try {
|
|
3993
|
+
return structuredClone(value);
|
|
3994
|
+
} catch (_) {
|
|
3995
|
+
// Fall through to the recursive clone below.
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3999
|
+
if (Array.isArray(value)) {
|
|
4000
|
+
return value.map(function (item) {
|
|
4001
|
+
return func.runtime.render.safe_clone_tree_value(item);
|
|
4002
|
+
});
|
|
4003
|
+
}
|
|
4004
|
+
|
|
4005
|
+
if (value && typeof value === 'object') {
|
|
4006
|
+
const cloned = {};
|
|
4007
|
+
const keys = Object.keys(value);
|
|
4008
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4009
|
+
const key = keys[index];
|
|
4010
|
+
cloned[key] = func.runtime.render.safe_clone_tree_value(value[key]);
|
|
4011
|
+
}
|
|
4012
|
+
return cloned;
|
|
4013
|
+
}
|
|
4014
|
+
|
|
4015
|
+
return value;
|
|
4016
|
+
};
|
|
4017
|
+
func.runtime.render.sort_tree_debug_value = function (value) {
|
|
4018
|
+
if (Array.isArray(value)) {
|
|
4019
|
+
return value.map(function (item) {
|
|
4020
|
+
return func.runtime.render.sort_tree_debug_value(item);
|
|
4021
|
+
});
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
if (value && typeof value === 'object') {
|
|
4025
|
+
const sorted = {};
|
|
4026
|
+
const keys = Object.keys(value).sort();
|
|
4027
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4028
|
+
const key = keys[index];
|
|
4029
|
+
sorted[key] = func.runtime.render.sort_tree_debug_value(value[key]);
|
|
4030
|
+
}
|
|
4031
|
+
return sorted;
|
|
4032
|
+
}
|
|
4033
|
+
|
|
4034
|
+
return value;
|
|
4035
|
+
};
|
|
4036
|
+
func.runtime.render.is_tree_node = function (nodeP) {
|
|
4037
|
+
return !!nodeP?.contract && nodeP.contract === func.runtime.render.TREE_CONTRACT_VERSION;
|
|
4038
|
+
};
|
|
4039
|
+
func.runtime.render.get_tree_source_node = function (nodeP) {
|
|
4040
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
4041
|
+
return nodeP || null;
|
|
4042
|
+
}
|
|
4043
|
+
return nodeP?.meta?.source_node || null;
|
|
4044
|
+
};
|
|
4045
|
+
func.runtime.render.get_tree_source_snapshot = function (nodeP) {
|
|
4046
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
4047
|
+
return func.runtime.render.safe_clone_tree_value(nodeP);
|
|
4048
|
+
}
|
|
4049
|
+
return nodeP?.meta?.source_snapshot || null;
|
|
4050
|
+
};
|
|
4051
|
+
func.runtime.render.get_tree_node_kind = function (nodeP) {
|
|
4052
|
+
const tag_name = typeof nodeP?.tagName === 'string' ? nodeP.tagName.toLowerCase() : '';
|
|
4053
|
+
const node_type = typeof nodeP?.type === 'string' ? nodeP.type.toLowerCase() : '';
|
|
4054
|
+
|
|
4055
|
+
if (tag_name === 'xu-widget') return 'widget';
|
|
4056
|
+
if (tag_name === 'xu-single-view') return 'single_view';
|
|
4057
|
+
if (tag_name === 'xu-multi-view') return 'multi_view';
|
|
4058
|
+
if (tag_name === 'xu-panel') return 'panel';
|
|
4059
|
+
if (tag_name === 'xu-teleport') return 'teleport';
|
|
4060
|
+
if (tag_name === 'xurender') return 'placeholder';
|
|
4061
|
+
if (tag_name === '#text' || node_type === 'text') return 'text';
|
|
4062
|
+
if (!tag_name && typeof nodeP?.content === 'string' && !Array.isArray(nodeP?.children)) return 'text';
|
|
4063
|
+
return 'element';
|
|
4064
|
+
};
|
|
4065
|
+
func.runtime.render.get_tree_node_id = function (nodeP, pathP) {
|
|
4066
|
+
if (nodeP?.id) {
|
|
4067
|
+
return nodeP.id;
|
|
4068
|
+
}
|
|
4069
|
+
if (nodeP?.id_org) {
|
|
4070
|
+
return nodeP.id_org;
|
|
4071
|
+
}
|
|
4072
|
+
const normalized_path = Array.isArray(pathP) && pathP.length ? pathP.join('.') : 'root';
|
|
4073
|
+
return `tree-node-${normalized_path}`;
|
|
4074
|
+
};
|
|
4075
|
+
func.runtime.render.get_tree_controls = function (attributes) {
|
|
4076
|
+
const attrs = attributes || {};
|
|
4077
|
+
const get_first_defined = function (keys) {
|
|
4078
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4079
|
+
const key = keys[index];
|
|
4080
|
+
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
|
|
4081
|
+
return attrs[key];
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
return null;
|
|
4085
|
+
};
|
|
4086
|
+
return {
|
|
4087
|
+
xu_for: get_first_defined(['xu-for', 'xu-exp:xu-for']),
|
|
4088
|
+
xu_if: get_first_defined(['xu-if', 'xu-exp:xu-if']),
|
|
4089
|
+
xu_render: get_first_defined(['xu-render', 'xu-exp:xu-render']),
|
|
4090
|
+
};
|
|
4091
|
+
};
|
|
4092
|
+
func.runtime.render.get_tree_node_capabilities = async function (options) {
|
|
4093
|
+
const attributes = options?.attributes || {};
|
|
4094
|
+
const plugin_name = attributes['xu-widget'];
|
|
4095
|
+
if (!plugin_name) {
|
|
4096
|
+
return null;
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
const cache = func.runtime.render._tree_widget_capability_cache;
|
|
4100
|
+
if (cache[plugin_name]) {
|
|
4101
|
+
return func.runtime.render.safe_clone_tree_value(cache[plugin_name]);
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
let capabilities = {
|
|
4105
|
+
browser: true,
|
|
4106
|
+
headless: false,
|
|
4107
|
+
};
|
|
4108
|
+
|
|
4109
|
+
try {
|
|
4110
|
+
if (options.SESSION_ID && options.paramsP && func.runtime.widgets?.create_context && func.runtime.widgets?.get_definition) {
|
|
4111
|
+
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, attributes);
|
|
4112
|
+
const definition = await func.runtime.widgets.get_definition(widget_context);
|
|
4113
|
+
capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
4114
|
+
}
|
|
4115
|
+
} catch (_) {
|
|
4116
|
+
// Keep the safe browser-only default when the widget definition is unavailable.
|
|
4117
|
+
}
|
|
4118
|
+
|
|
4119
|
+
cache[plugin_name] = capabilities;
|
|
4120
|
+
return func.runtime.render.safe_clone_tree_value(capabilities);
|
|
4121
|
+
};
|
|
4122
|
+
func.runtime.render.ensure_tree_node = async function (options) {
|
|
4123
|
+
if (!options?.nodeP) {
|
|
4124
|
+
return null;
|
|
4125
|
+
}
|
|
4126
|
+
if (func.runtime.render.is_tree_node(options.nodeP)) {
|
|
4127
|
+
return options.nodeP;
|
|
4128
|
+
}
|
|
4129
|
+
return await func.runtime.render.build_tree(options);
|
|
4130
|
+
};
|
|
4131
|
+
func.runtime.render.build_tree = async function (options) {
|
|
4132
|
+
if (Array.isArray(options?.nodeP)) {
|
|
4133
|
+
return await func.runtime.render.build_tree_list({
|
|
4134
|
+
...options,
|
|
4135
|
+
nodesP: options.nodeP,
|
|
4136
|
+
});
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4139
|
+
const nodeP = options?.nodeP;
|
|
4140
|
+
if (!nodeP) {
|
|
4141
|
+
return null;
|
|
4142
|
+
}
|
|
4143
|
+
if (func.runtime.render.is_tree_node(nodeP)) {
|
|
4144
|
+
return nodeP;
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4147
|
+
const pathP = Array.isArray(options?.pathP) ? options.pathP.slice() : [];
|
|
4148
|
+
const tree_path = pathP.length ? pathP.slice() : [0];
|
|
4149
|
+
const attributes = func.runtime.render.safe_clone_tree_value(nodeP.attributes || {});
|
|
4150
|
+
if (typeof nodeP.content !== 'undefined' && typeof attributes['xu-content'] === 'undefined') {
|
|
4151
|
+
attributes['xu-content'] = func.runtime.render.safe_clone_tree_value(nodeP.content);
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
const widget_capabilities = await func.runtime.render.get_tree_node_capabilities({
|
|
4155
|
+
SESSION_ID: options?.SESSION_ID,
|
|
4156
|
+
paramsP: options?.paramsP,
|
|
4157
|
+
attributes,
|
|
4158
|
+
});
|
|
4159
|
+
const children = [];
|
|
4160
|
+
const child_nodes = Array.isArray(nodeP.children) ? nodeP.children : [];
|
|
4161
|
+
const parent_tree_id = tree_path.join('.');
|
|
4162
|
+
|
|
4163
|
+
for (let index = 0; index < child_nodes.length; index++) {
|
|
4164
|
+
const child_tree = await func.runtime.render.build_tree({
|
|
4165
|
+
...options,
|
|
4166
|
+
nodeP: child_nodes[index],
|
|
4167
|
+
pathP: tree_path.concat(index),
|
|
4168
|
+
parent_tree_id: parent_tree_id,
|
|
4169
|
+
keyP: index,
|
|
4170
|
+
parent_nodeP: nodeP,
|
|
4171
|
+
});
|
|
4172
|
+
if (child_tree) {
|
|
4173
|
+
children.push(child_tree);
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4177
|
+
const tree = {
|
|
4178
|
+
contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
4179
|
+
id: func.runtime.render.get_tree_node_id(nodeP, tree_path),
|
|
4180
|
+
xu_tree_id: `tree.${tree_path.join('.')}`,
|
|
4181
|
+
kind: func.runtime.render.get_tree_node_kind(nodeP),
|
|
4182
|
+
tagName: nodeP.tagName || null,
|
|
4183
|
+
attributes,
|
|
4184
|
+
text: typeof nodeP.text !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.text) : null,
|
|
4185
|
+
content: typeof nodeP.content !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.content) : null,
|
|
4186
|
+
children,
|
|
4187
|
+
meta: {
|
|
4188
|
+
tree_id: tree_path.join('.'),
|
|
4189
|
+
path: tree_path,
|
|
4190
|
+
parent_tree_id: options?.parent_tree_id || null,
|
|
4191
|
+
key: typeof options?.keyP === 'undefined' ? null : options.keyP,
|
|
4192
|
+
recordid: nodeP?.recordid || null,
|
|
4193
|
+
dependency_fields: func.runtime.render.safe_clone_tree_value(nodeP?.dependency_fields || null),
|
|
4194
|
+
iterate_info: func.runtime.render.safe_clone_tree_value(options?.parent_infoP?.iterate_info || nodeP?.iterate_info || null),
|
|
4195
|
+
controls: func.runtime.render.get_tree_controls(attributes),
|
|
4196
|
+
capabilities: widget_capabilities,
|
|
4197
|
+
widget: attributes['xu-widget']
|
|
4198
|
+
? {
|
|
4199
|
+
plugin_name: attributes['xu-widget'],
|
|
4200
|
+
method: attributes['xu-method'] || '_default',
|
|
4201
|
+
capabilities: widget_capabilities,
|
|
4202
|
+
}
|
|
4203
|
+
: null,
|
|
4204
|
+
source_node_id: nodeP?.id || nodeP?.id_org || null,
|
|
4205
|
+
source_node: nodeP,
|
|
4206
|
+
source_snapshot: func.runtime.ui?.get_node_snapshot
|
|
4207
|
+
? func.runtime.ui.get_node_snapshot(nodeP)
|
|
4208
|
+
: func.runtime.render.safe_clone_tree_value(nodeP),
|
|
4209
|
+
},
|
|
4210
|
+
};
|
|
4211
|
+
|
|
4212
|
+
return tree;
|
|
4213
|
+
};
|
|
4214
|
+
func.runtime.render.build_tree_list = async function (options) {
|
|
4215
|
+
const nodes = Array.isArray(options?.nodesP) ? options.nodesP : [];
|
|
4216
|
+
const trees = [];
|
|
4217
|
+
|
|
4218
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
4219
|
+
const tree = await func.runtime.render.build_tree({
|
|
4220
|
+
...options,
|
|
4221
|
+
nodeP: nodes[index],
|
|
4222
|
+
pathP: Array.isArray(options?.pathP) && options.pathP.length ? options.pathP.concat(index) : [index],
|
|
4223
|
+
keyP: index,
|
|
4224
|
+
});
|
|
4225
|
+
if (tree) {
|
|
4226
|
+
trees.push(tree);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
return trees;
|
|
4231
|
+
};
|
|
4232
|
+
func.runtime.render.sanitize_tree_for_debug = function (treeP) {
|
|
4233
|
+
if (Array.isArray(treeP)) {
|
|
4234
|
+
return treeP.map(function (child) {
|
|
4235
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
4236
|
+
});
|
|
4237
|
+
}
|
|
4238
|
+
|
|
4239
|
+
if (!func.runtime.render.is_tree_node(treeP)) {
|
|
4240
|
+
return func.runtime.render.sort_tree_debug_value(func.runtime.render.safe_clone_tree_value(treeP));
|
|
4241
|
+
}
|
|
4242
|
+
|
|
4243
|
+
return {
|
|
4244
|
+
contract: treeP.contract,
|
|
4245
|
+
id: treeP.id,
|
|
4246
|
+
xu_tree_id: treeP.xu_tree_id || null,
|
|
4247
|
+
kind: treeP.kind,
|
|
4248
|
+
tagName: treeP.tagName,
|
|
4249
|
+
attributes: func.runtime.render.sort_tree_debug_value(treeP.attributes || {}),
|
|
4250
|
+
text: treeP.text,
|
|
4251
|
+
content: treeP.content,
|
|
4252
|
+
children: treeP.children.map(function (child) {
|
|
4253
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
4254
|
+
}),
|
|
4255
|
+
meta: {
|
|
4256
|
+
tree_id: treeP.meta?.tree_id || null,
|
|
4257
|
+
path: func.runtime.render.safe_clone_tree_value(treeP.meta?.path || []),
|
|
4258
|
+
parent_tree_id: treeP.meta?.parent_tree_id || null,
|
|
4259
|
+
key: typeof treeP.meta?.key === 'undefined' ? null : treeP.meta.key,
|
|
4260
|
+
recordid: treeP.meta?.recordid || null,
|
|
4261
|
+
dependency_fields: func.runtime.render.sort_tree_debug_value(treeP.meta?.dependency_fields || null),
|
|
4262
|
+
iterate_info: func.runtime.render.sort_tree_debug_value(treeP.meta?.iterate_info || null),
|
|
4263
|
+
controls: func.runtime.render.sort_tree_debug_value(treeP.meta?.controls || null),
|
|
4264
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta?.capabilities || null),
|
|
4265
|
+
widget: treeP.meta?.widget
|
|
4266
|
+
? {
|
|
4267
|
+
plugin_name: treeP.meta.widget.plugin_name,
|
|
4268
|
+
method: treeP.meta.widget.method,
|
|
4269
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta.widget.capabilities || null),
|
|
4270
|
+
}
|
|
4271
|
+
: null,
|
|
4272
|
+
source_node_id: treeP.meta?.source_node_id || null,
|
|
4273
|
+
},
|
|
4274
|
+
};
|
|
4275
|
+
};
|
|
4276
|
+
func.runtime.render.serialize_tree = function (treeP, spacing = 2) {
|
|
4277
|
+
return JSON.stringify(func.runtime.render.sanitize_tree_for_debug(treeP), null, spacing);
|
|
4278
|
+
};
|
|
4279
|
+
func.runtime = func.runtime || {};
|
|
4280
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
4281
|
+
func.runtime.render = func.runtime.render || {};
|
|
4282
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
4283
|
+
|
|
4284
|
+
// Shared string-renderer helpers live here so headless/server runtimes can materialize the render tree without a DOM.
|
|
4285
|
+
|
|
4286
|
+
func.runtime.render.HTML_VOID_TAGS = func.runtime.render.HTML_VOID_TAGS || {
|
|
4287
|
+
area: true,
|
|
4288
|
+
base: true,
|
|
4289
|
+
br: true,
|
|
4290
|
+
col: true,
|
|
4291
|
+
embed: true,
|
|
4292
|
+
hr: true,
|
|
4293
|
+
img: true,
|
|
4294
|
+
input: true,
|
|
4295
|
+
link: true,
|
|
4296
|
+
meta: true,
|
|
4297
|
+
param: true,
|
|
4298
|
+
source: true,
|
|
4299
|
+
track: true,
|
|
4300
|
+
wbr: true,
|
|
4301
|
+
};
|
|
4302
|
+
func.runtime.render.escape_html = function (value) {
|
|
4303
|
+
return `${value ?? ''}`
|
|
4304
|
+
.replaceAll('&', '&')
|
|
4305
|
+
.replaceAll('<', '<')
|
|
4306
|
+
.replaceAll('>', '>')
|
|
4307
|
+
.replaceAll('"', '"')
|
|
4308
|
+
.replaceAll("'", ''');
|
|
4309
|
+
};
|
|
4310
|
+
func.runtime.render.escape_html_attribute = function (value) {
|
|
4311
|
+
return func.runtime.render.escape_html(value);
|
|
4312
|
+
};
|
|
4313
|
+
func.runtime.render.is_html_void_tag = function (tag_name) {
|
|
4314
|
+
return !!func.runtime.render.HTML_VOID_TAGS[(tag_name || '').toLowerCase()];
|
|
4315
|
+
};
|
|
4316
|
+
func.runtime.render.is_falsey_render_value = function (value) {
|
|
4317
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
4318
|
+
return true;
|
|
4319
|
+
}
|
|
4320
|
+
if (typeof value === 'number') {
|
|
4321
|
+
return value === 0;
|
|
4322
|
+
}
|
|
4323
|
+
if (typeof value === 'string') {
|
|
4324
|
+
const normalized = value.trim().toLowerCase();
|
|
4325
|
+
return normalized === '' || normalized === 'false' || normalized === '0' || normalized === 'null' || normalized === 'undefined' || normalized === 'off' || normalized === 'no';
|
|
4326
|
+
}
|
|
4327
|
+
return false;
|
|
4328
|
+
};
|
|
4329
|
+
func.runtime.render.should_render_tree_node = function (treeP) {
|
|
4330
|
+
const controls = treeP?.meta?.controls || {};
|
|
4331
|
+
if (controls.xu_if !== null && controls.xu_if !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_if)) {
|
|
4332
|
+
return false;
|
|
4333
|
+
}
|
|
4334
|
+
if (controls.xu_render !== null && controls.xu_render !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_render)) {
|
|
4335
|
+
return false;
|
|
4336
|
+
}
|
|
4337
|
+
return true;
|
|
4338
|
+
};
|
|
4339
|
+
func.runtime.render.is_tree_control_attribute = function (key) {
|
|
4340
|
+
if (!key) {
|
|
4341
|
+
return false;
|
|
4342
|
+
}
|
|
4343
|
+
return (
|
|
4344
|
+
key.startsWith('xu-exp:') ||
|
|
4345
|
+
key === 'xu-widget' ||
|
|
4346
|
+
key === 'xu-method' ||
|
|
4347
|
+
key === 'xu-for' ||
|
|
4348
|
+
key === 'xu-for-key' ||
|
|
4349
|
+
key === 'xu-for-val' ||
|
|
4350
|
+
key === 'xu-if' ||
|
|
4351
|
+
key === 'xu-render' ||
|
|
4352
|
+
key === 'xu-bind' ||
|
|
4353
|
+
key === 'xu-content' ||
|
|
4354
|
+
key === 'xu-text' ||
|
|
4355
|
+
key === 'xu-html' ||
|
|
4356
|
+
key === 'xu-show' ||
|
|
4357
|
+
key === 'xu-panel-program' ||
|
|
4358
|
+
key === 'xu-teleport'
|
|
4359
|
+
);
|
|
4360
|
+
};
|
|
4361
|
+
func.runtime.render.get_string_renderer_tag_name = function (treeP) {
|
|
4362
|
+
switch (treeP?.kind) {
|
|
4363
|
+
case 'widget':
|
|
4364
|
+
case 'single_view':
|
|
4365
|
+
case 'multi_view':
|
|
4366
|
+
case 'panel':
|
|
4367
|
+
case 'teleport':
|
|
4368
|
+
return 'div';
|
|
4369
|
+
case 'placeholder':
|
|
4370
|
+
return null;
|
|
4371
|
+
case 'text':
|
|
4372
|
+
return null;
|
|
4373
|
+
default:
|
|
4374
|
+
return treeP?.tagName || 'div';
|
|
4375
|
+
}
|
|
4376
|
+
};
|
|
4377
|
+
func.runtime.render.get_tree_terminal_content = function (treeP) {
|
|
4378
|
+
const attributes = treeP?.attributes || {};
|
|
4379
|
+
if (typeof attributes['xu-html'] !== 'undefined' && attributes['xu-html'] !== null) {
|
|
4380
|
+
return {
|
|
4381
|
+
value: `${attributes['xu-html']}`,
|
|
4382
|
+
mode: 'html',
|
|
4383
|
+
};
|
|
4384
|
+
}
|
|
4385
|
+
if (typeof attributes['xu-content'] !== 'undefined' && attributes['xu-content'] !== null) {
|
|
4386
|
+
return {
|
|
4387
|
+
value: `${attributes['xu-content']}`,
|
|
4388
|
+
mode: 'html',
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
4391
|
+
if (typeof attributes['xu-text'] !== 'undefined' && attributes['xu-text'] !== null) {
|
|
4392
|
+
return {
|
|
4393
|
+
value: `${attributes['xu-text']}`,
|
|
4394
|
+
mode: 'text',
|
|
4395
|
+
};
|
|
4396
|
+
}
|
|
4397
|
+
if (treeP?.kind === 'text') {
|
|
4398
|
+
return {
|
|
4399
|
+
value: typeof treeP?.text !== 'undefined' && treeP?.text !== null ? `${treeP.text}` : `${treeP?.content || ''}`,
|
|
4400
|
+
mode: 'text',
|
|
4401
|
+
};
|
|
4402
|
+
}
|
|
4403
|
+
return null;
|
|
4404
|
+
};
|
|
4405
|
+
func.runtime.render.render_tree_terminal_content = function (treeP) {
|
|
4406
|
+
const terminal = func.runtime.render.get_tree_terminal_content(treeP);
|
|
4407
|
+
if (!terminal) {
|
|
4408
|
+
return null;
|
|
4409
|
+
}
|
|
4410
|
+
if (terminal.mode === 'html') {
|
|
4411
|
+
return terminal.value;
|
|
4412
|
+
}
|
|
4413
|
+
return func.runtime.render.escape_html(terminal.value);
|
|
4414
|
+
};
|
|
4415
|
+
func.runtime.render.get_widget_fallback_markup = function (treeP) {
|
|
4416
|
+
const widget_meta = treeP?.meta?.widget || {};
|
|
4417
|
+
const capability_state = widget_meta?.capabilities?.headless ? 'headless-capable' : 'browser-only';
|
|
4418
|
+
return `<!--xuda-widget:${func.runtime.render.escape_html(widget_meta.plugin_name || 'unknown')}:${capability_state}-->`;
|
|
4419
|
+
};
|
|
4420
|
+
func.runtime.render.get_tree_string_attributes = function (treeP, renderer_context) {
|
|
4421
|
+
const attributes = func.runtime.render.safe_clone_tree_value(treeP?.attributes || {});
|
|
4422
|
+
const attr_pairs = [];
|
|
4423
|
+
const keys = Object.keys(attributes);
|
|
4424
|
+
|
|
4425
|
+
for (let index = 0; index < keys.length; index++) {
|
|
4426
|
+
const key = keys[index];
|
|
4427
|
+
if (func.runtime.render.is_tree_control_attribute(key)) {
|
|
4428
|
+
continue;
|
|
4429
|
+
}
|
|
4430
|
+
const value = attributes[key];
|
|
4431
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
4432
|
+
continue;
|
|
4433
|
+
}
|
|
4434
|
+
if (value === true) {
|
|
4435
|
+
attr_pairs.push(key);
|
|
4436
|
+
continue;
|
|
4437
|
+
}
|
|
4438
|
+
const normalized_value = typeof value === 'object' ? JSON.stringify(value) : `${value}`;
|
|
4439
|
+
attr_pairs.push(`${key}="${func.runtime.render.escape_html_attribute(normalized_value)}"`);
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
attr_pairs.push(`data-xuda-kind="${func.runtime.render.escape_html_attribute(treeP?.kind || 'element')}"`);
|
|
4443
|
+
attr_pairs.push(`data-xuda-node-id="${func.runtime.render.escape_html_attribute(treeP?.id || treeP?.meta?.source_node_id || '')}"`);
|
|
4444
|
+
attr_pairs.push(`data-xuda-tree-id="${func.runtime.render.escape_html_attribute(treeP?.meta?.tree_id || '')}"`);
|
|
4445
|
+
|
|
4446
|
+
if (treeP?.kind === 'widget' && treeP?.meta?.widget) {
|
|
4447
|
+
attr_pairs.push(`data-xuda-widget="${func.runtime.render.escape_html_attribute(treeP.meta.widget.plugin_name || '')}"`);
|
|
4448
|
+
attr_pairs.push(`data-xuda-widget-method="${func.runtime.render.escape_html_attribute(treeP.meta.widget.method || '_default')}"`);
|
|
4449
|
+
attr_pairs.push(`data-xuda-widget-capability="${func.runtime.render.escape_html_attribute(treeP.meta.widget.capabilities?.headless ? 'headless' : 'browser')}"`);
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
if (treeP?.kind === 'teleport' && treeP?.attributes?.['xu-teleport']) {
|
|
4453
|
+
attr_pairs.push(`data-xuda-teleport-target="${func.runtime.render.escape_html_attribute(treeP.attributes['xu-teleport'])}"`);
|
|
4454
|
+
}
|
|
4455
|
+
|
|
4456
|
+
if ((treeP?.meta?.controls?.xu_for !== null && treeP?.meta?.controls?.xu_for !== undefined) && !renderer_context?.strip_iteration_markers) {
|
|
4457
|
+
attr_pairs.push('data-xuda-xu-for="pending"');
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
return attr_pairs.length ? ' ' + attr_pairs.join(' ') : '';
|
|
4461
|
+
};
|
|
4462
|
+
func.runtime.render.render_tree_children_to_string = async function (treeP, renderer_context) {
|
|
4463
|
+
if (!Array.isArray(treeP?.children) || !treeP.children.length) {
|
|
4464
|
+
return '';
|
|
4465
|
+
}
|
|
4466
|
+
let html = '';
|
|
4467
|
+
for (let index = 0; index < treeP.children.length; index++) {
|
|
4468
|
+
html += await func.runtime.render.render_tree_to_string(treeP.children[index], {
|
|
4469
|
+
...renderer_context,
|
|
4470
|
+
parent_tree: treeP,
|
|
4471
|
+
});
|
|
4472
|
+
}
|
|
4473
|
+
return html;
|
|
4474
|
+
};
|
|
4475
|
+
func.runtime.render.render_tree_to_string = async function (treeP, renderer_context = {}) {
|
|
4476
|
+
if (!treeP) {
|
|
4477
|
+
return '';
|
|
4478
|
+
}
|
|
4479
|
+
if (Array.isArray(treeP)) {
|
|
4480
|
+
let html = '';
|
|
4481
|
+
for (let index = 0; index < treeP.length; index++) {
|
|
4482
|
+
html += await func.runtime.render.render_tree_to_string(treeP[index], renderer_context);
|
|
4483
|
+
}
|
|
4484
|
+
return html;
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4487
|
+
const ensured_tree = await func.runtime.render.ensure_tree_node({
|
|
4488
|
+
SESSION_ID: renderer_context?.SESSION_ID,
|
|
4489
|
+
nodeP: treeP,
|
|
4490
|
+
paramsP: renderer_context?.paramsP,
|
|
4491
|
+
parent_infoP: renderer_context?.parent_infoP,
|
|
4492
|
+
keyP: renderer_context?.keyP,
|
|
4493
|
+
parent_nodeP: renderer_context?.parent_nodeP,
|
|
4494
|
+
});
|
|
4495
|
+
|
|
4496
|
+
if (!ensured_tree || !func.runtime.render.should_render_tree_node(ensured_tree)) {
|
|
4497
|
+
return '';
|
|
4498
|
+
}
|
|
4499
|
+
|
|
4500
|
+
if (ensured_tree.kind === 'placeholder') {
|
|
4501
|
+
if (renderer_context?.include_placeholders) {
|
|
4502
|
+
return `<!--xuda-placeholder:${func.runtime.render.escape_html(ensured_tree.id || '')}-->`;
|
|
4503
|
+
}
|
|
4504
|
+
return '';
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
if (ensured_tree.kind === 'text') {
|
|
4508
|
+
return func.runtime.render.render_tree_terminal_content(ensured_tree) || '';
|
|
4509
|
+
}
|
|
4510
|
+
|
|
4511
|
+
const tag_name = func.runtime.render.get_string_renderer_tag_name(ensured_tree);
|
|
4512
|
+
if (!tag_name || tag_name.toLowerCase() === 'script') {
|
|
4513
|
+
return '';
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4516
|
+
const attributes = func.runtime.render.get_tree_string_attributes(ensured_tree, renderer_context);
|
|
4517
|
+
const terminal_content = func.runtime.render.render_tree_terminal_content(ensured_tree);
|
|
4518
|
+
let children_html = terminal_content !== null ? terminal_content : await func.runtime.render.render_tree_children_to_string(ensured_tree, renderer_context);
|
|
4519
|
+
|
|
4520
|
+
if (ensured_tree.kind === 'widget' && !children_html) {
|
|
4521
|
+
children_html = func.runtime.render.get_widget_fallback_markup(ensured_tree);
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
if (func.runtime.render.is_html_void_tag(tag_name)) {
|
|
4525
|
+
return `<${tag_name}${attributes}>`;
|
|
4526
|
+
}
|
|
4527
|
+
|
|
4528
|
+
return `<${tag_name}${attributes}>${children_html}</${tag_name}>`;
|
|
4529
|
+
};
|
|
4530
|
+
func.runtime.render.render_to_string = async function (options = {}) {
|
|
4531
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
4532
|
+
SESSION_ID: options.SESSION_ID,
|
|
4533
|
+
nodeP: options.treeP || options.nodeP,
|
|
4534
|
+
paramsP: options.paramsP,
|
|
4535
|
+
parent_infoP: options.parent_infoP,
|
|
4536
|
+
keyP: options.keyP,
|
|
4537
|
+
parent_nodeP: options.parent_nodeP,
|
|
4538
|
+
});
|
|
4539
|
+
|
|
4540
|
+
return await func.runtime.render.render_tree_to_string(treeP, options);
|
|
4541
|
+
};
|
|
4542
|
+
func.runtime.render.get_server_render_mode = function (options = {}) {
|
|
4543
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap({
|
|
4544
|
+
app_computing_mode: options.app_computing_mode,
|
|
4545
|
+
app_render_mode: options.app_render_mode,
|
|
4546
|
+
app_client_activation: options.app_client_activation,
|
|
4547
|
+
});
|
|
4548
|
+
|
|
4549
|
+
return normalized;
|
|
4550
|
+
};
|
|
4551
|
+
func.runtime.render.build_server_render_params = async function (options = {}) {
|
|
4552
|
+
const SESSION_ID = options.SESSION_ID;
|
|
4553
|
+
const prog_id = options.prog_id;
|
|
4554
|
+
const dsSessionP = options.dsSessionP;
|
|
4555
|
+
const _session = SESSION_OBJ?.[SESSION_ID] || {};
|
|
4556
|
+
const _ds = _session?.DS_GLB?.[dsSessionP] || {};
|
|
4557
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
4558
|
+
|
|
4559
|
+
if (!viewDoc?.properties) {
|
|
4560
|
+
throw new Error(`view document not found for ${prog_id}`);
|
|
4561
|
+
}
|
|
3750
4562
|
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
4563
|
+
const base_params = _ds?.screen_params ? func.runtime.render.safe_clone_tree_value(_ds.screen_params) : {};
|
|
4564
|
+
const screenId = options.screenId || base_params.screenId || `ssr_${prog_id}_${dsSessionP || '0'}`;
|
|
4565
|
+
const paramsP = {
|
|
4566
|
+
...base_params,
|
|
4567
|
+
prog_id,
|
|
4568
|
+
sourceScreenP: null,
|
|
4569
|
+
$callingContainerP: null,
|
|
4570
|
+
triggerIdP: null,
|
|
4571
|
+
callingDataSource_objP: _ds,
|
|
4572
|
+
rowIdP: typeof options.rowIdP !== 'undefined' ? options.rowIdP : (_ds?.currentRecordId || null),
|
|
4573
|
+
renderType: viewDoc.properties?.renderType,
|
|
4574
|
+
parameters_obj_inP: options.parameters_obj_inP || base_params.parameters_obj_inP || options.parameters_raw_obj || {},
|
|
4575
|
+
source_functionP: options.source_functionP || base_params.source_functionP || 'render_string',
|
|
4576
|
+
is_panelP: false,
|
|
4577
|
+
screen_type: options.screen_type || base_params.screen_type || 'render_string',
|
|
4578
|
+
screenInfo: viewDoc,
|
|
4579
|
+
call_screen_propertiesP: base_params.call_screen_propertiesP,
|
|
4580
|
+
parentDataSourceNoP: typeof _ds?.parentDataSourceNo === 'undefined' || _ds?.parentDataSourceNo === null ? 0 : _ds.parentDataSourceNo,
|
|
4581
|
+
parameters_raw_obj: options.parameters_raw_obj || base_params.parameters_raw_obj || {},
|
|
4582
|
+
dsSessionP,
|
|
4583
|
+
screenId,
|
|
4584
|
+
containerIdP: base_params.containerIdP || `ssr_container_${screenId}`,
|
|
4585
|
+
};
|
|
3755
4586
|
|
|
3756
|
-
|
|
3757
|
-
|
|
4587
|
+
if (_ds) {
|
|
4588
|
+
_ds.screen_params = paramsP;
|
|
4589
|
+
}
|
|
3758
4590
|
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
4591
|
+
return paramsP;
|
|
4592
|
+
};
|
|
4593
|
+
func.runtime.render.build_prog_tree = async function (options = {}) {
|
|
4594
|
+
const SESSION_ID = options.SESSION_ID;
|
|
4595
|
+
const prog_id = options.prog_id;
|
|
4596
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
4597
|
+
|
|
4598
|
+
if (!viewDoc?.progUi?.length) {
|
|
4599
|
+
throw new Error(`progUi not found for ${prog_id}`);
|
|
3763
4600
|
}
|
|
3764
4601
|
|
|
3765
|
-
|
|
3766
|
-
|
|
4602
|
+
const paramsP = options.paramsP || (await func.runtime.render.build_server_render_params({
|
|
4603
|
+
...options,
|
|
4604
|
+
SESSION_ID,
|
|
4605
|
+
prog_id,
|
|
4606
|
+
viewDoc,
|
|
4607
|
+
}));
|
|
4608
|
+
const root_index = typeof options.root_index === 'number' ? options.root_index : 0;
|
|
4609
|
+
const root_node = func.runtime.render.safe_clone_tree_value(viewDoc.progUi[root_index]);
|
|
4610
|
+
const tree = await func.runtime.render.build_tree({
|
|
4611
|
+
SESSION_ID,
|
|
4612
|
+
nodeP: root_node,
|
|
4613
|
+
paramsP,
|
|
4614
|
+
});
|
|
4615
|
+
|
|
4616
|
+
return {
|
|
4617
|
+
tree,
|
|
4618
|
+
paramsP,
|
|
4619
|
+
viewDoc,
|
|
4620
|
+
};
|
|
3767
4621
|
};
|
|
4622
|
+
func.runtime.render.build_ssr_payload = function (render_program, options = {}) {
|
|
4623
|
+
const runtime_profile = func.runtime.render.get_server_render_mode(options);
|
|
4624
|
+
return {
|
|
4625
|
+
contract: 'xuda.ssr.v1',
|
|
4626
|
+
prog_id: options.prog_id,
|
|
4627
|
+
screenId: render_program.paramsP.screenId,
|
|
4628
|
+
containerId: render_program.paramsP.containerIdP,
|
|
4629
|
+
app_computing_mode: runtime_profile.app_computing_mode,
|
|
4630
|
+
app_render_mode: runtime_profile.app_render_mode,
|
|
4631
|
+
app_client_activation: runtime_profile.app_client_activation,
|
|
4632
|
+
tree_contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
4633
|
+
};
|
|
4634
|
+
};
|
|
4635
|
+
func.runtime.render.build_ssr_screen_html = function (html, render_program, options = {}) {
|
|
4636
|
+
const payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
4637
|
+
const screenId = func.runtime.render.escape_html_attribute(payload.screenId || '');
|
|
4638
|
+
const containerId = func.runtime.render.escape_html_attribute(payload.containerId || '');
|
|
4639
|
+
const activation = func.runtime.render.escape_html_attribute(payload.app_client_activation || 'takeover');
|
|
4640
|
+
|
|
4641
|
+
return `<div data-xuda-ssr-embed="true" class="xu_embed_div"><div id="${screenId}" class="xu_embed_container" data-xuda-ssr-screen="true" data-xuda-ssr-screen-id="${screenId}" data-xuda-activation="${activation}" style="display: contents;"><div id="${containerId}" data-xuda-ssr-root-frame="true" data-xuda-ssr-screen-id="${screenId}" data-xuda-activation="${activation}" style="display: contents;">${html}</div></div></div>`;
|
|
4642
|
+
};
|
|
4643
|
+
func.runtime.render.render_prog_to_string = async function (options = {}) {
|
|
4644
|
+
const render_program = await func.runtime.render.build_prog_tree(options);
|
|
4645
|
+
const html = await func.runtime.render.render_to_string({
|
|
4646
|
+
...options,
|
|
4647
|
+
SESSION_ID: options.SESSION_ID,
|
|
4648
|
+
treeP: render_program.tree,
|
|
4649
|
+
paramsP: render_program.paramsP,
|
|
4650
|
+
});
|
|
4651
|
+
const ssr_payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
4652
|
+
const screen_html = func.runtime.render.build_ssr_screen_html(html, render_program, options);
|
|
3768
4653
|
|
|
3769
|
-
|
|
4654
|
+
return {
|
|
4655
|
+
prog_id: options.prog_id,
|
|
4656
|
+
dsSessionP: render_program.paramsP.dsSessionP,
|
|
4657
|
+
screenId: render_program.paramsP.screenId,
|
|
4658
|
+
html,
|
|
4659
|
+
screen_html,
|
|
4660
|
+
tree_json: func.runtime.render.serialize_tree(render_program.tree),
|
|
4661
|
+
paramsP: render_program.paramsP,
|
|
4662
|
+
ssr_payload,
|
|
4663
|
+
};
|
|
4664
|
+
};
|
|
3770
4665
|
func.runtime = func.runtime || {};
|
|
3771
4666
|
func.runtime.platform = func.runtime.platform || {};
|
|
3772
4667
|
|
|
@@ -9156,6 +10051,15 @@ func.runtime.ui.ensure_embed_container = function (SESSION_ID) {
|
|
|
9156
10051
|
const $root_element = func.runtime.ui.get_root_element(SESSION_ID);
|
|
9157
10052
|
let $embed_container = func.runtime.ui.find_by_selector($root_element, `#embed_${SESSION_ID}`, true);
|
|
9158
10053
|
|
|
10054
|
+
if (!$embed_container.length) {
|
|
10055
|
+
const $ssr_embed_container = func.runtime.ui.find_by_selector($root_element, `[data-xuda-ssr-embed="true"]`, true);
|
|
10056
|
+
const ssr_embed_node = func.runtime.ui.get_first_node($ssr_embed_container);
|
|
10057
|
+
if (ssr_embed_node) {
|
|
10058
|
+
ssr_embed_node.id = 'embed_' + SESSION_ID;
|
|
10059
|
+
$embed_container = func.runtime.ui._wrap_matches([ssr_embed_node]);
|
|
10060
|
+
}
|
|
10061
|
+
}
|
|
10062
|
+
|
|
9159
10063
|
if (!$embed_container.length) {
|
|
9160
10064
|
const embed_node = document.createElement('div');
|
|
9161
10065
|
embed_node.id = 'embed_' + SESSION_ID;
|
|
@@ -9191,12 +10095,44 @@ func.runtime.ui.get_root_tag_name = function () {
|
|
|
9191
10095
|
}
|
|
9192
10096
|
return root_tag_name;
|
|
9193
10097
|
};
|
|
10098
|
+
func.runtime.ui.find_ssr_screen_host = function ($container, screenId, containerId) {
|
|
10099
|
+
const container_node = func.runtime.ui.get_first_node($container);
|
|
10100
|
+
if (!container_node || !screenId) {
|
|
10101
|
+
return null;
|
|
10102
|
+
}
|
|
10103
|
+
|
|
10104
|
+
const dialog_node =
|
|
10105
|
+
container_node.querySelector?.(`#${CSS?.escape ? CSS.escape(screenId) : screenId}`) ||
|
|
10106
|
+
container_node.querySelector?.(`[data-xuda-ssr-screen-id="${screenId}"]`);
|
|
10107
|
+
if (!dialog_node) {
|
|
10108
|
+
return null;
|
|
10109
|
+
}
|
|
10110
|
+
|
|
10111
|
+
const root_frame_node =
|
|
10112
|
+
(containerId ? dialog_node.querySelector?.(`#${CSS?.escape ? CSS.escape(containerId) : containerId}`) : null) ||
|
|
10113
|
+
dialog_node.querySelector?.('[data-xuda-ssr-root-frame="true"]');
|
|
10114
|
+
if (!root_frame_node) {
|
|
10115
|
+
return null;
|
|
10116
|
+
}
|
|
10117
|
+
|
|
10118
|
+
return {
|
|
10119
|
+
$dialogDiv: func.runtime.ui._wrap_matches([dialog_node]),
|
|
10120
|
+
$rootFrame: func.runtime.ui._wrap_matches([root_frame_node]),
|
|
10121
|
+
reused_ssr_host: true,
|
|
10122
|
+
};
|
|
10123
|
+
};
|
|
9194
10124
|
func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params, $callingContainerP, screenId) {
|
|
9195
10125
|
var $dialogDiv;
|
|
9196
10126
|
var $rootFrame;
|
|
10127
|
+
let reused_ssr_host = false;
|
|
9197
10128
|
|
|
9198
10129
|
switch (screen_type) {
|
|
9199
10130
|
case 'embed': {
|
|
10131
|
+
const ssr_host = func.runtime.ui.find_ssr_screen_host($callingContainerP, screenId, params?.containerIdP);
|
|
10132
|
+
if (ssr_host) {
|
|
10133
|
+
return ssr_host;
|
|
10134
|
+
}
|
|
10135
|
+
|
|
9200
10136
|
const dialogNode = document.createElement('div');
|
|
9201
10137
|
dialogNode.id = screenId;
|
|
9202
10138
|
dialogNode.setAttribute('ui_engine', UI_FRAMEWORK_INSTALLED);
|
|
@@ -9246,6 +10182,7 @@ func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params,
|
|
|
9246
10182
|
return {
|
|
9247
10183
|
$dialogDiv,
|
|
9248
10184
|
$rootFrame,
|
|
10185
|
+
reused_ssr_host,
|
|
9249
10186
|
};
|
|
9250
10187
|
};
|
|
9251
10188
|
func.runtime.ui.find_xu_ui_in_root = function (SESSION_ID, xu_ui_id) {
|
|
@@ -9810,6 +10747,11 @@ func.runtime.ui.build_container_xu_data = function (options) {
|
|
|
9810
10747
|
func.runtime.ui.apply_container_meta = function ($div, options) {
|
|
9811
10748
|
const div_node = func.runtime.ui.get_first_node($div);
|
|
9812
10749
|
func.runtime.ui.set_attr(div_node, 'xu-ui-id', options.ui_id);
|
|
10750
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-kind', options.treeP?.kind || options.nodeP?.tagName || 'element');
|
|
10751
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-node-id', options.nodeP?.id || options.nodeP?.id_org || '');
|
|
10752
|
+
if (options.treeP?.meta?.tree_id !== null && typeof options.treeP?.meta?.tree_id !== 'undefined') {
|
|
10753
|
+
func.runtime.ui.set_attr(div_node, 'data-xuda-tree-id', options.treeP.meta.tree_id);
|
|
10754
|
+
}
|
|
9813
10755
|
const xuData = func.runtime.ui.build_container_xu_data(options);
|
|
9814
10756
|
if (options.parent_infoP?.iterate_info) {
|
|
9815
10757
|
xuData.iterate_info = options.parent_infoP.iterate_info;
|
|
@@ -9904,6 +10846,38 @@ func.runtime.ui.create_container_element = function (div_typeP, attr_str, prop,
|
|
|
9904
10846
|
}
|
|
9905
10847
|
return func.runtime.ui.create_element(div, attr_str);
|
|
9906
10848
|
};
|
|
10849
|
+
func.runtime.ui.find_hydration_candidate = function (options) {
|
|
10850
|
+
if (!func.runtime.render.is_hydration_mode(SESSION_OBJ?.[options.SESSION_ID])) {
|
|
10851
|
+
return null;
|
|
10852
|
+
}
|
|
10853
|
+
if (!func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
10854
|
+
return null;
|
|
10855
|
+
}
|
|
10856
|
+
if (options.is_placeholder || !options.treeP?.meta?.tree_id) {
|
|
10857
|
+
return null;
|
|
10858
|
+
}
|
|
10859
|
+
|
|
10860
|
+
const append_node = func.runtime.ui.get_first_node(options.$appendTo || options.$container);
|
|
10861
|
+
if (!append_node) {
|
|
10862
|
+
return null;
|
|
10863
|
+
}
|
|
10864
|
+
|
|
10865
|
+
const children = func.runtime.ui.get_children(append_node);
|
|
10866
|
+
for (let index = 0; index < children.length; index++) {
|
|
10867
|
+
const child = children[index];
|
|
10868
|
+
if (child?.__xuda_hydration_claimed) {
|
|
10869
|
+
continue;
|
|
10870
|
+
}
|
|
10871
|
+
if (func.runtime.ui.get_attr(child, 'data-xuda-tree-id') !== `${options.treeP.meta.tree_id}`) {
|
|
10872
|
+
continue;
|
|
10873
|
+
}
|
|
10874
|
+
child.__xuda_hydration_claimed = true;
|
|
10875
|
+
func.runtime.ui.set_attr(child, 'data-xuda-client-activation', 'hydrate');
|
|
10876
|
+
return child;
|
|
10877
|
+
}
|
|
10878
|
+
|
|
10879
|
+
return null;
|
|
10880
|
+
};
|
|
9907
10881
|
func.runtime.ui.build_xu_ui_id_seed = function (nodeP, dsSessionP, key_path, currentRecordId) {
|
|
9908
10882
|
const nodeId = nodeP.xu_tree_id || nodeP.id;
|
|
9909
10883
|
const elem_key = `${nodeId}-${key_path}-${currentRecordId}`;
|
|
@@ -9956,7 +10930,11 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
9956
10930
|
try {
|
|
9957
10931
|
const key_path = func.runtime.ui.build_container_key_path(container_xu_data, options.keyP, options.parent_infoP, options.nodeP, options.parent_nodeP);
|
|
9958
10932
|
const elem_key = `${options.nodeP.xu_tree_id || options.nodeP.id}-${key_path}-${currentRecordId}`;
|
|
9959
|
-
const
|
|
10933
|
+
const hydration_candidate = func.runtime.ui.find_hydration_candidate({
|
|
10934
|
+
...options,
|
|
10935
|
+
$appendTo,
|
|
10936
|
+
});
|
|
10937
|
+
const $div = hydration_candidate || func.runtime.ui.create_container_element(options.div_typeP, options.attr_str, options.prop, options.nodeP, $appendTo);
|
|
9960
10938
|
const new_ui_id = await func.runtime.ui.generate_xu_ui_id(options.SESSION_ID, options.nodeP, options.$container, options.paramsP, options.keyP, {
|
|
9961
10939
|
container_xu_data,
|
|
9962
10940
|
currentRecordId,
|
|
@@ -9982,9 +10960,10 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
9982
10960
|
parent_infoP: options.parent_infoP,
|
|
9983
10961
|
is_placeholder: options.is_placeholder,
|
|
9984
10962
|
classP: options.classP,
|
|
10963
|
+
treeP: options.treeP,
|
|
9985
10964
|
});
|
|
9986
10965
|
|
|
9987
|
-
if (options.div_typeP !== 'svg') {
|
|
10966
|
+
if (!hydration_candidate && options.div_typeP !== 'svg') {
|
|
9988
10967
|
func.runtime.ui.append_to($div, $appendTo);
|
|
9989
10968
|
}
|
|
9990
10969
|
return $div;
|
|
@@ -12665,9 +13644,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12665
13644
|
|
|
12666
13645
|
const _session = SESSION_OBJ[SESSION_ID];
|
|
12667
13646
|
const screenInfo = structuredClone(screen_ret);
|
|
13647
|
+
const ssr_payload = func.runtime.render.should_use_ssr_payload(SESSION_ID, { prog_id }) ? func.runtime.render.get_ssr_payload(_session) : null;
|
|
12668
13648
|
|
|
12669
13649
|
const screen_type = source_functionP?.split('_')?.[1];
|
|
12670
|
-
const screenId = (glb.screen_num++).toString();
|
|
13650
|
+
const screenId = ssr_payload?.screenId || (glb.screen_num++).toString();
|
|
12671
13651
|
|
|
12672
13652
|
if (SCREEN_BLOCKER_OBJ[prog_id + (sourceScreenP ? '_' + sourceScreenP : '')]) {
|
|
12673
13653
|
const wait_for_SCREEN_BLOCKER_release = function () {
|
|
@@ -12709,6 +13689,8 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12709
13689
|
call_screen_propertiesP,
|
|
12710
13690
|
parentDataSourceNoP: _session.DS_GLB?.[callingDataSource_objP?.dsSession]?.dsSession || callingDataSource_objP?.parentDataSourceNo || 0,
|
|
12711
13691
|
parameters_raw_obj,
|
|
13692
|
+
containerIdP: ssr_payload?.containerId || null,
|
|
13693
|
+
ssr_payload,
|
|
12712
13694
|
};
|
|
12713
13695
|
|
|
12714
13696
|
const screen_host = func.runtime.ui.create_screen_host(SESSION_ID, screen_type, params, $callingContainerP, screenId);
|
|
@@ -12741,6 +13723,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12741
13723
|
func.runtime.ui.set_style($rootFrame, 'display', 'contents');
|
|
12742
13724
|
}
|
|
12743
13725
|
|
|
13726
|
+
if (screen_host.reused_ssr_host && func.runtime.render.is_takeover_mode(_session)) {
|
|
13727
|
+
func.runtime.ui.empty($rootFrame);
|
|
13728
|
+
}
|
|
13729
|
+
|
|
12744
13730
|
if (!is_panelP) func.UI.utils.indicator.screen.busy();
|
|
12745
13731
|
|
|
12746
13732
|
const ret = await func.datasource.create(
|
|
@@ -12782,7 +13768,24 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12782
13768
|
}
|
|
12783
13769
|
let node = structuredClone(viewDoc.progUi);
|
|
12784
13770
|
if (!node.length) return console.warn('ui node empty');
|
|
12785
|
-
const
|
|
13771
|
+
const root_tree = await func.runtime.render.build_tree({
|
|
13772
|
+
SESSION_ID,
|
|
13773
|
+
nodeP: node[0],
|
|
13774
|
+
paramsP: params,
|
|
13775
|
+
});
|
|
13776
|
+
const ret_render_$container = await func.runtime.render.render_tree(root_tree, {
|
|
13777
|
+
SESSION_ID,
|
|
13778
|
+
$container: $rootFrame,
|
|
13779
|
+
parent_infoP: null,
|
|
13780
|
+
paramsP: params,
|
|
13781
|
+
jobNoP,
|
|
13782
|
+
is_skeleton: null,
|
|
13783
|
+
keyP: null,
|
|
13784
|
+
refreshed_ds: null,
|
|
13785
|
+
parent_nodeP: null,
|
|
13786
|
+
check_existP: null,
|
|
13787
|
+
$root_container: $rootFrame,
|
|
13788
|
+
});
|
|
12786
13789
|
|
|
12787
13790
|
if (!is_panelP) func.UI.utils.indicator.screen.normal();
|
|
12788
13791
|
|
|
@@ -13207,6 +14210,7 @@ func.runtime.ui.render_single_view_node = async function (options) {
|
|
|
13207
14210
|
parent_infoP: options.parent_infoP,
|
|
13208
14211
|
jobNoP: options.jobNoP,
|
|
13209
14212
|
keyP: options.keyP,
|
|
14213
|
+
treeP: options.treeP,
|
|
13210
14214
|
parent_nodeP: options.parent_nodeP,
|
|
13211
14215
|
prop: options.prop,
|
|
13212
14216
|
div_typeP: 'div',
|
|
@@ -13335,6 +14339,7 @@ func.runtime.ui.render_panel_node = async function (options) {
|
|
|
13335
14339
|
parent_infoP: options.parent_infoP,
|
|
13336
14340
|
jobNoP: options.jobNoP,
|
|
13337
14341
|
keyP: options.keyP,
|
|
14342
|
+
treeP: options.treeP,
|
|
13338
14343
|
parent_nodeP: options.parent_nodeP,
|
|
13339
14344
|
prop: options.prop,
|
|
13340
14345
|
$appendToP: $wrapper,
|
|
@@ -13664,6 +14669,14 @@ func.runtime.ui.screen_loading_done = async function (options) {
|
|
|
13664
14669
|
});
|
|
13665
14670
|
|
|
13666
14671
|
const _session = SESSION_OBJ[options.SESSION_ID];
|
|
14672
|
+
if (func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
14673
|
+
const root_node = func.runtime.ui.get_root_node(options.SESSION_ID);
|
|
14674
|
+
if (root_node) {
|
|
14675
|
+
func.runtime.ui.set_attr(root_node, 'data-xuda-client-activation', _session.opt.app_client_activation || 'none');
|
|
14676
|
+
func.runtime.ui.set_attr(root_node, 'data-xuda-ssr-status', _session.opt.app_client_activation === 'hydrate' ? 'hydrated' : 'taken-over');
|
|
14677
|
+
}
|
|
14678
|
+
func.runtime.render.mark_ssr_payload_consumed(options.SESSION_ID);
|
|
14679
|
+
}
|
|
13667
14680
|
func.events.delete_job(options.SESSION_ID, options.jobNoP);
|
|
13668
14681
|
func.UI.utils.screen_blocker(false, options.paramsP.prog_id + (options.paramsP.sourceScreenP ? '_' + options.paramsP.sourceScreenP : ''));
|
|
13669
14682
|
if (_session.prog_id === options.paramsP.prog_id) {
|
|
@@ -15506,6 +16519,9 @@ func.runtime.render.get_screen_context = function (SESSION_ID, $container, param
|
|
|
15506
16519
|
};
|
|
15507
16520
|
func.runtime.render.get_node_attributes = function (nodeP) {
|
|
15508
16521
|
try {
|
|
16522
|
+
if (func.runtime.render.is_tree_node?.(nodeP)) {
|
|
16523
|
+
return nodeP.attributes;
|
|
16524
|
+
}
|
|
15509
16525
|
return nodeP?.attributes;
|
|
15510
16526
|
} catch (error) {
|
|
15511
16527
|
return undefined;
|
|
@@ -15623,6 +16639,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15623
16639
|
parent_infoP: options.parent_infoP,
|
|
15624
16640
|
jobNoP: options.jobNoP,
|
|
15625
16641
|
keyP: options.keyP,
|
|
16642
|
+
treeP: options.treeP,
|
|
15626
16643
|
parent_nodeP: options.parent_nodeP,
|
|
15627
16644
|
prop: options.prop,
|
|
15628
16645
|
div_typeP: options.element,
|
|
@@ -15645,6 +16662,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15645
16662
|
parent_infoP: options.parent_infoP,
|
|
15646
16663
|
jobNoP: options.jobNoP,
|
|
15647
16664
|
keyP: options.keyP,
|
|
16665
|
+
treeP: options.treeP,
|
|
15648
16666
|
parent_nodeP: options.parent_nodeP,
|
|
15649
16667
|
prop: options.prop,
|
|
15650
16668
|
div_typeP: options.element,
|
|
@@ -16501,11 +17519,16 @@ func.runtime.widgets.render_node = async function (options) {
|
|
|
16501
17519
|
parent_infoP: options.parent_infoP,
|
|
16502
17520
|
jobNoP: options.jobNoP,
|
|
16503
17521
|
keyP: options.keyP,
|
|
17522
|
+
treeP: options.treeP,
|
|
16504
17523
|
parent_nodeP: options.parent_nodeP,
|
|
16505
17524
|
prop: options.prop,
|
|
16506
17525
|
classP: 'widget_wrapper',
|
|
16507
17526
|
});
|
|
16508
17527
|
|
|
17528
|
+
if (func.runtime.render.is_hydration_mode(SESSION_OBJ?.[options.SESSION_ID]) && func.runtime.render.should_use_ssr_payload(options.SESSION_ID, options.paramsP)) {
|
|
17529
|
+
func.runtime.ui.empty($div);
|
|
17530
|
+
}
|
|
17531
|
+
|
|
16509
17532
|
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, options.prop);
|
|
16510
17533
|
const { plugin_name, method, propsP, plugin: _plugin } = widget_context;
|
|
16511
17534
|
const report_error = function (descP, warn) {
|
|
@@ -16608,9 +17631,306 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16608
17631
|
|
|
16609
17632
|
// Browser-only special node renderers live here so the core render tree can stay focused.
|
|
16610
17633
|
|
|
17634
|
+
const normalize_runtime_tag_name = function (tag_name) {
|
|
17635
|
+
return `${tag_name || ''}`.trim().toLowerCase();
|
|
17636
|
+
};
|
|
17637
|
+
|
|
17638
|
+
const get_runtime_node_attributes = function (nodeP) {
|
|
17639
|
+
if (!nodeP?.attributes || typeof nodeP.attributes !== 'object') {
|
|
17640
|
+
return {};
|
|
17641
|
+
}
|
|
17642
|
+
|
|
17643
|
+
return nodeP.attributes;
|
|
17644
|
+
};
|
|
17645
|
+
|
|
17646
|
+
const get_runtime_node_content = function (nodeP) {
|
|
17647
|
+
if (typeof nodeP?.content === 'string') {
|
|
17648
|
+
return nodeP.content;
|
|
17649
|
+
}
|
|
17650
|
+
|
|
17651
|
+
if (typeof nodeP?.text === 'string') {
|
|
17652
|
+
return nodeP.text;
|
|
17653
|
+
}
|
|
17654
|
+
|
|
17655
|
+
if (!Array.isArray(nodeP?.children)) {
|
|
17656
|
+
return '';
|
|
17657
|
+
}
|
|
17658
|
+
|
|
17659
|
+
return nodeP.children
|
|
17660
|
+
.map(function (child) {
|
|
17661
|
+
if (typeof child === 'string') {
|
|
17662
|
+
return child;
|
|
17663
|
+
}
|
|
17664
|
+
if (typeof child?.content === 'string') {
|
|
17665
|
+
return child.content;
|
|
17666
|
+
}
|
|
17667
|
+
if (typeof child?.text === 'string') {
|
|
17668
|
+
return child.text;
|
|
17669
|
+
}
|
|
17670
|
+
return '';
|
|
17671
|
+
})
|
|
17672
|
+
.join('');
|
|
17673
|
+
};
|
|
17674
|
+
|
|
17675
|
+
const get_runtime_asset_key = function (options, tag_name) {
|
|
17676
|
+
const source_node = options.treeP || options.nodeP || {};
|
|
17677
|
+
const parts = [
|
|
17678
|
+
'xuda-html-asset',
|
|
17679
|
+
options.paramsP?.prog_id || '',
|
|
17680
|
+
tag_name,
|
|
17681
|
+
source_node.id || source_node.id_org || '',
|
|
17682
|
+
typeof options.keyP === 'undefined' || options.keyP === null ? '' : `${options.keyP}`,
|
|
17683
|
+
].filter(function (part) {
|
|
17684
|
+
return `${part || ''}`.trim() !== '';
|
|
17685
|
+
});
|
|
17686
|
+
|
|
17687
|
+
return parts.join(':');
|
|
17688
|
+
};
|
|
17689
|
+
|
|
17690
|
+
const get_runtime_asset_signature = function (attributes, content) {
|
|
17691
|
+
const normalized_attributes = {};
|
|
17692
|
+
const attr_keys = Object.keys(attributes || {}).sort();
|
|
17693
|
+
|
|
17694
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
17695
|
+
const key = attr_keys[index];
|
|
17696
|
+
normalized_attributes[key] = attributes[key];
|
|
17697
|
+
}
|
|
17698
|
+
|
|
17699
|
+
return JSON.stringify({
|
|
17700
|
+
attributes: normalized_attributes,
|
|
17701
|
+
content: `${content || ''}`,
|
|
17702
|
+
});
|
|
17703
|
+
};
|
|
17704
|
+
|
|
17705
|
+
const escape_runtime_asset_selector_value = function (value) {
|
|
17706
|
+
const win = func.runtime.platform.get_window?.();
|
|
17707
|
+
if (win?.CSS?.escape) {
|
|
17708
|
+
return win.CSS.escape(value);
|
|
17709
|
+
}
|
|
17710
|
+
|
|
17711
|
+
return `${value || ''}`.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
17712
|
+
};
|
|
17713
|
+
|
|
17714
|
+
const find_runtime_head_asset = function (head, tag_name, asset_key) {
|
|
17715
|
+
if (!head?.querySelector || !asset_key) {
|
|
17716
|
+
return null;
|
|
17717
|
+
}
|
|
17718
|
+
|
|
17719
|
+
return head.querySelector(`${tag_name}[data-xuda-asset-key="${escape_runtime_asset_selector_value(asset_key)}"]`);
|
|
17720
|
+
};
|
|
17721
|
+
|
|
17722
|
+
const find_runtime_head_asset_by_attr = function (head, tag_name, attr_name, attr_value) {
|
|
17723
|
+
if (!head?.querySelectorAll || !attr_name || !attr_value) {
|
|
17724
|
+
return null;
|
|
17725
|
+
}
|
|
17726
|
+
|
|
17727
|
+
const candidates = Array.from(head.querySelectorAll(tag_name));
|
|
17728
|
+
return (
|
|
17729
|
+
candidates.find(function (candidate) {
|
|
17730
|
+
return candidate.getAttribute(attr_name) === attr_value || candidate[attr_name] === attr_value;
|
|
17731
|
+
}) || null
|
|
17732
|
+
);
|
|
17733
|
+
};
|
|
17734
|
+
|
|
17735
|
+
const wait_for_runtime_asset_load = function (node) {
|
|
17736
|
+
if (!node?.addEventListener) {
|
|
17737
|
+
return Promise.resolve(node);
|
|
17738
|
+
}
|
|
17739
|
+
|
|
17740
|
+
if (node.getAttribute?.('data-xuda-loaded') === 'true') {
|
|
17741
|
+
return Promise.resolve(node);
|
|
17742
|
+
}
|
|
17743
|
+
|
|
17744
|
+
if (!node.getAttribute?.('data-xuda-asset-key')) {
|
|
17745
|
+
return Promise.resolve(node);
|
|
17746
|
+
}
|
|
17747
|
+
|
|
17748
|
+
const tag_name = normalize_runtime_tag_name(node.tagName);
|
|
17749
|
+
if (tag_name !== 'script' && !(tag_name === 'link' && normalize_runtime_tag_name(node.getAttribute?.('rel')) === 'stylesheet')) {
|
|
17750
|
+
return Promise.resolve(node);
|
|
17751
|
+
}
|
|
17752
|
+
|
|
17753
|
+
return new Promise(function (resolve) {
|
|
17754
|
+
const done = function () {
|
|
17755
|
+
node.setAttribute?.('data-xuda-loaded', 'true');
|
|
17756
|
+
resolve(node);
|
|
17757
|
+
};
|
|
17758
|
+
|
|
17759
|
+
node.addEventListener('load', done, { once: true });
|
|
17760
|
+
node.addEventListener('error', done, { once: true });
|
|
17761
|
+
});
|
|
17762
|
+
};
|
|
17763
|
+
|
|
17764
|
+
const remove_runtime_head_asset = function (node) {
|
|
17765
|
+
if (node?.parentNode?.removeChild) {
|
|
17766
|
+
node.parentNode.removeChild(node);
|
|
17767
|
+
}
|
|
17768
|
+
};
|
|
17769
|
+
|
|
17770
|
+
const apply_runtime_asset_metadata = function (node, asset_key, signature) {
|
|
17771
|
+
if (!node?.setAttribute) {
|
|
17772
|
+
return node;
|
|
17773
|
+
}
|
|
17774
|
+
|
|
17775
|
+
if (asset_key) {
|
|
17776
|
+
node.setAttribute('data-xuda-asset-key', asset_key);
|
|
17777
|
+
}
|
|
17778
|
+
node.setAttribute('data-xuda-asset-signature', signature);
|
|
17779
|
+
return node;
|
|
17780
|
+
};
|
|
17781
|
+
|
|
17782
|
+
const create_runtime_head_element = function (doc, tag_name, attributes, asset_key, signature) {
|
|
17783
|
+
const node = doc.createElement(tag_name);
|
|
17784
|
+
apply_runtime_asset_metadata(node, asset_key, signature);
|
|
17785
|
+
func.runtime.platform.apply_element_attributes(node, attributes);
|
|
17786
|
+
return node;
|
|
17787
|
+
};
|
|
17788
|
+
|
|
17789
|
+
const upsert_runtime_head_element = async function (options) {
|
|
17790
|
+
const doc = func.runtime.platform.get_document?.();
|
|
17791
|
+
const head = doc?.head;
|
|
17792
|
+
const tag_name = normalize_runtime_tag_name(options.tag_name);
|
|
17793
|
+
|
|
17794
|
+
if (!doc?.createElement || !head?.appendChild || !tag_name) {
|
|
17795
|
+
return null;
|
|
17796
|
+
}
|
|
17797
|
+
|
|
17798
|
+
const asset_key = options.asset_key || '';
|
|
17799
|
+
const signature = options.signature || '';
|
|
17800
|
+
const attributes = options.attributes || {};
|
|
17801
|
+
const content = typeof options.content === 'string' ? options.content : '';
|
|
17802
|
+
|
|
17803
|
+
const existing_by_key = find_runtime_head_asset(head, tag_name, asset_key);
|
|
17804
|
+
if (existing_by_key && existing_by_key.getAttribute('data-xuda-asset-signature') === signature) {
|
|
17805
|
+
return options.await_load ? await wait_for_runtime_asset_load(existing_by_key) : existing_by_key;
|
|
17806
|
+
}
|
|
17807
|
+
|
|
17808
|
+
if (existing_by_key) {
|
|
17809
|
+
remove_runtime_head_asset(existing_by_key);
|
|
17810
|
+
}
|
|
17811
|
+
|
|
17812
|
+
if (options.find_existing_attr?.name && options.find_existing_attr?.value) {
|
|
17813
|
+
const existing_by_attr = find_runtime_head_asset_by_attr(head, tag_name, options.find_existing_attr.name, options.find_existing_attr.value);
|
|
17814
|
+
if (existing_by_attr) {
|
|
17815
|
+
apply_runtime_asset_metadata(existing_by_attr, asset_key, signature);
|
|
17816
|
+
existing_by_attr.setAttribute?.('data-xuda-loaded', 'true');
|
|
17817
|
+
return existing_by_attr;
|
|
17818
|
+
}
|
|
17819
|
+
}
|
|
17820
|
+
|
|
17821
|
+
const node = create_runtime_head_element(doc, tag_name, attributes, asset_key, signature);
|
|
17822
|
+
|
|
17823
|
+
if (tag_name === 'script' && attributes.src && !Object.prototype.hasOwnProperty.call(attributes, 'async')) {
|
|
17824
|
+
const script_type = normalize_runtime_tag_name(attributes.type);
|
|
17825
|
+
if (script_type !== 'module') {
|
|
17826
|
+
node.async = false;
|
|
17827
|
+
}
|
|
17828
|
+
}
|
|
17829
|
+
|
|
17830
|
+
if (tag_name === 'style' || (tag_name === 'script' && !attributes.src)) {
|
|
17831
|
+
node.textContent = content;
|
|
17832
|
+
}
|
|
17833
|
+
|
|
17834
|
+
head.appendChild(node);
|
|
17835
|
+
|
|
17836
|
+
if (tag_name !== 'script' && tag_name !== 'link') {
|
|
17837
|
+
node.setAttribute('data-xuda-loaded', 'true');
|
|
17838
|
+
}
|
|
17839
|
+
|
|
17840
|
+
return options.await_load ? await wait_for_runtime_asset_load(node) : node;
|
|
17841
|
+
};
|
|
17842
|
+
|
|
17843
|
+
const render_runtime_html_asset = async function (options) {
|
|
17844
|
+
if (options.is_skeleton) {
|
|
17845
|
+
return options.$container;
|
|
17846
|
+
}
|
|
17847
|
+
|
|
17848
|
+
const nodeP = options.treeP || options.nodeP || {};
|
|
17849
|
+
const tag_name = normalize_runtime_tag_name(nodeP.tagName);
|
|
17850
|
+
const attributes = { ...get_runtime_node_attributes(nodeP) };
|
|
17851
|
+
const content = get_runtime_node_content(nodeP);
|
|
17852
|
+
const asset_key = get_runtime_asset_key(options, tag_name);
|
|
17853
|
+
const signature = get_runtime_asset_signature(attributes, content);
|
|
17854
|
+
|
|
17855
|
+
switch (tag_name) {
|
|
17856
|
+
case 'title':
|
|
17857
|
+
func.runtime.platform.set_title(content);
|
|
17858
|
+
return options.$container;
|
|
17859
|
+
case 'style':
|
|
17860
|
+
await upsert_runtime_head_element({
|
|
17861
|
+
tag_name,
|
|
17862
|
+
attributes,
|
|
17863
|
+
content,
|
|
17864
|
+
asset_key,
|
|
17865
|
+
signature,
|
|
17866
|
+
});
|
|
17867
|
+
return options.$container;
|
|
17868
|
+
case 'meta':
|
|
17869
|
+
if (!Object.keys(attributes).length) {
|
|
17870
|
+
return options.$container;
|
|
17871
|
+
}
|
|
17872
|
+
await upsert_runtime_head_element({
|
|
17873
|
+
tag_name,
|
|
17874
|
+
attributes,
|
|
17875
|
+
asset_key,
|
|
17876
|
+
signature,
|
|
17877
|
+
});
|
|
17878
|
+
return options.$container;
|
|
17879
|
+
case 'link': {
|
|
17880
|
+
const href = `${attributes.href || ''}`.trim();
|
|
17881
|
+
if (!href) {
|
|
17882
|
+
return options.$container;
|
|
17883
|
+
}
|
|
17884
|
+
await upsert_runtime_head_element({
|
|
17885
|
+
tag_name,
|
|
17886
|
+
attributes,
|
|
17887
|
+
asset_key,
|
|
17888
|
+
signature,
|
|
17889
|
+
find_existing_attr: {
|
|
17890
|
+
name: 'href',
|
|
17891
|
+
value: href,
|
|
17892
|
+
},
|
|
17893
|
+
await_load: normalize_runtime_tag_name(attributes.rel) === 'stylesheet',
|
|
17894
|
+
});
|
|
17895
|
+
return options.$container;
|
|
17896
|
+
}
|
|
17897
|
+
case 'script': {
|
|
17898
|
+
const src = `${attributes.src || ''}`.trim();
|
|
17899
|
+
if (!src && !content.trim()) {
|
|
17900
|
+
return options.$container;
|
|
17901
|
+
}
|
|
17902
|
+
await upsert_runtime_head_element({
|
|
17903
|
+
tag_name,
|
|
17904
|
+
attributes,
|
|
17905
|
+
content,
|
|
17906
|
+
asset_key,
|
|
17907
|
+
signature,
|
|
17908
|
+
find_existing_attr: src
|
|
17909
|
+
? {
|
|
17910
|
+
name: 'src',
|
|
17911
|
+
value: src,
|
|
17912
|
+
}
|
|
17913
|
+
: null,
|
|
17914
|
+
await_load: !!src,
|
|
17915
|
+
});
|
|
17916
|
+
return options.$container;
|
|
17917
|
+
}
|
|
17918
|
+
default:
|
|
17919
|
+
return null;
|
|
17920
|
+
}
|
|
17921
|
+
};
|
|
17922
|
+
|
|
16611
17923
|
func.runtime.render.render_special_node = async function (options) {
|
|
16612
|
-
|
|
16613
|
-
|
|
17924
|
+
const treeP = options.treeP || null;
|
|
17925
|
+
const nodeP = options.nodeP || func.runtime.render.get_tree_source_node(treeP);
|
|
17926
|
+
const render_tag_name = treeP?.tagName || nodeP?.tagName;
|
|
17927
|
+
const normalized_render_tag_name = normalize_runtime_tag_name(render_tag_name);
|
|
17928
|
+
const is_native_html_asset = ['title', 'style', 'meta', 'link', 'script'].includes(normalized_render_tag_name);
|
|
17929
|
+
|
|
17930
|
+
if (!is_native_html_asset && treeP?.content && nodeP?.attributes) {
|
|
17931
|
+
nodeP.attributes['xu-content'] = treeP.content;
|
|
17932
|
+
} else if (!is_native_html_asset && nodeP?.content && nodeP.attributes) {
|
|
17933
|
+
nodeP.attributes['xu-content'] = nodeP.content;
|
|
16614
17934
|
}
|
|
16615
17935
|
|
|
16616
17936
|
const renderers = {
|
|
@@ -16620,6 +17940,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16620
17940
|
SESSION_ID: options.SESSION_ID,
|
|
16621
17941
|
$container: options.$container,
|
|
16622
17942
|
$root_container: options.$root_container,
|
|
17943
|
+
treeP,
|
|
16623
17944
|
nodeP: options.nodeP,
|
|
16624
17945
|
parent_infoP: options.parent_infoP,
|
|
16625
17946
|
paramsP: options.paramsP,
|
|
@@ -16636,6 +17957,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16636
17957
|
SESSION_ID: options.SESSION_ID,
|
|
16637
17958
|
$container: options.$container,
|
|
16638
17959
|
$root_container: options.$root_container,
|
|
17960
|
+
treeP,
|
|
16639
17961
|
nodeP: options.nodeP,
|
|
16640
17962
|
parent_infoP: options.parent_infoP,
|
|
16641
17963
|
paramsP: options.paramsP,
|
|
@@ -16655,6 +17977,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16655
17977
|
SESSION_ID: options.SESSION_ID,
|
|
16656
17978
|
$container: options.$container,
|
|
16657
17979
|
$root_container: options.$root_container,
|
|
17980
|
+
treeP,
|
|
16658
17981
|
nodeP: options.nodeP,
|
|
16659
17982
|
parent_infoP: options.parent_infoP,
|
|
16660
17983
|
paramsP: options.paramsP,
|
|
@@ -16671,6 +17994,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16671
17994
|
SESSION_ID: options.SESSION_ID,
|
|
16672
17995
|
$container: options.$container,
|
|
16673
17996
|
$root_container: options.$root_container,
|
|
17997
|
+
treeP,
|
|
16674
17998
|
nodeP: options.nodeP,
|
|
16675
17999
|
parent_infoP: options.parent_infoP,
|
|
16676
18000
|
paramsP: options.paramsP,
|
|
@@ -16682,9 +18006,24 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16682
18006
|
refreshed_ds: options.refreshed_ds,
|
|
16683
18007
|
});
|
|
16684
18008
|
},
|
|
18009
|
+
title: async function () {
|
|
18010
|
+
return await render_runtime_html_asset(options);
|
|
18011
|
+
},
|
|
18012
|
+
style: async function () {
|
|
18013
|
+
return await render_runtime_html_asset(options);
|
|
18014
|
+
},
|
|
18015
|
+
meta: async function () {
|
|
18016
|
+
return await render_runtime_html_asset(options);
|
|
18017
|
+
},
|
|
18018
|
+
link: async function () {
|
|
18019
|
+
return await render_runtime_html_asset(options);
|
|
18020
|
+
},
|
|
18021
|
+
script: async function () {
|
|
18022
|
+
return await render_runtime_html_asset(options);
|
|
18023
|
+
},
|
|
16685
18024
|
};
|
|
16686
18025
|
|
|
16687
|
-
const renderer = renderers[
|
|
18026
|
+
const renderer = renderers[normalized_render_tag_name];
|
|
16688
18027
|
if (!renderer) {
|
|
16689
18028
|
return { handled: false };
|
|
16690
18029
|
}
|
|
@@ -16798,8 +18137,9 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16798
18137
|
// Browser-only render tree entrypoints live here so draw/cache helpers can stay focused.
|
|
16799
18138
|
|
|
16800
18139
|
func.runtime.render.create_tree_runtime = function (options) {
|
|
18140
|
+
const render_node = options.nodeP || func.runtime.render.get_tree_source_node(options.treeP);
|
|
16801
18141
|
const render_context = func.runtime.render.get_screen_context(options.SESSION_ID, options.$container, options.paramsP, options.is_skeleton);
|
|
16802
|
-
const prop = func.runtime.render.get_node_attributes(options.
|
|
18142
|
+
const prop = func.runtime.render.get_node_attributes(options.treeP || render_node);
|
|
16803
18143
|
const is_mobile = render_context.is_mobile ? true : false;
|
|
16804
18144
|
const hover_handlers = func.runtime.render.create_hover_handlers({
|
|
16805
18145
|
SESSION_ID: options.SESSION_ID,
|
|
@@ -16814,13 +18154,22 @@ func.runtime.render.create_tree_runtime = function (options) {
|
|
|
16814
18154
|
return await func.runtime.ui.close_modal_session(options.SESSION_ID, modal_id);
|
|
16815
18155
|
};
|
|
16816
18156
|
const iterate_child = async function ($divP, nodeP, parent_infoP, $root_container, before_record_function) {
|
|
18157
|
+
const child_tree = await func.runtime.render.ensure_tree_node({
|
|
18158
|
+
SESSION_ID: options.SESSION_ID,
|
|
18159
|
+
nodeP: nodeP || options.treeP || render_node,
|
|
18160
|
+
parent_infoP,
|
|
18161
|
+
paramsP: options.paramsP,
|
|
18162
|
+
keyP: options.keyP,
|
|
18163
|
+
parent_nodeP: render_node,
|
|
18164
|
+
pathP: options.treeP?.meta?.path || [],
|
|
18165
|
+
});
|
|
16817
18166
|
return await func.runtime.render.iterate_children({
|
|
16818
18167
|
$divP,
|
|
16819
|
-
nodeP,
|
|
18168
|
+
nodeP: child_tree,
|
|
16820
18169
|
is_mobile,
|
|
16821
18170
|
before_record_function,
|
|
16822
18171
|
render_child: async function (key, child) {
|
|
16823
|
-
await options.render_child($divP, child, parent_infoP, key,
|
|
18172
|
+
await options.render_child($divP, child, parent_infoP, key, render_node, $root_container);
|
|
16824
18173
|
},
|
|
16825
18174
|
});
|
|
16826
18175
|
};
|
|
@@ -16850,7 +18199,7 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16850
18199
|
check_existP: options.check_existP,
|
|
16851
18200
|
$root_container: options.$root_container,
|
|
16852
18201
|
prop: options.prop,
|
|
16853
|
-
element: options.nodeP.tagName,
|
|
18202
|
+
element: options.treeP?.tagName || options.nodeP.tagName,
|
|
16854
18203
|
hover_handlers: options.hover_handlers,
|
|
16855
18204
|
include_hover_click: options.include_hover_click,
|
|
16856
18205
|
iterate_child: options.iterate_child,
|
|
@@ -16873,21 +18222,33 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16873
18222
|
nodeP: options.nodeP,
|
|
16874
18223
|
});
|
|
16875
18224
|
};
|
|
16876
|
-
func.runtime.render.
|
|
16877
|
-
if (!
|
|
16878
|
-
const
|
|
16879
|
-
func.runtime?.perf?.
|
|
18225
|
+
func.runtime.render.render_tree = async function (treeP, renderer_context) {
|
|
18226
|
+
if (!treeP) return;
|
|
18227
|
+
const nodeP = func.runtime.render.get_tree_source_node(treeP);
|
|
18228
|
+
const perf_end = func.runtime?.perf?.start?.(renderer_context.SESSION_ID, 'render_ui_tree');
|
|
18229
|
+
func.runtime?.perf?.increment_map?.(renderer_context.SESSION_ID, 'render_node_counts', treeP.id || nodeP?.id || nodeP?.id_org || treeP.tagName || 'unknown');
|
|
16880
18230
|
try {
|
|
16881
18231
|
const tree_runtime = func.runtime.render.create_tree_runtime({
|
|
16882
|
-
SESSION_ID,
|
|
16883
|
-
$container,
|
|
18232
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18233
|
+
$container: renderer_context.$container,
|
|
18234
|
+
treeP,
|
|
16884
18235
|
nodeP,
|
|
16885
|
-
parent_infoP,
|
|
16886
|
-
paramsP,
|
|
16887
|
-
jobNoP,
|
|
16888
|
-
is_skeleton,
|
|
18236
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18237
|
+
paramsP: renderer_context.paramsP,
|
|
18238
|
+
jobNoP: renderer_context.jobNoP,
|
|
18239
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18240
|
+
keyP: renderer_context.keyP,
|
|
16889
18241
|
render_child: async function ($divP, child, parent_infoP, key, parentNodeP, rootContainerP) {
|
|
16890
|
-
await func.runtime.render.
|
|
18242
|
+
await func.runtime.render.render_tree(child, {
|
|
18243
|
+
...renderer_context,
|
|
18244
|
+
$container: $divP,
|
|
18245
|
+
parent_infoP,
|
|
18246
|
+
keyP: key,
|
|
18247
|
+
refreshed_ds: null,
|
|
18248
|
+
parent_nodeP: parentNodeP,
|
|
18249
|
+
check_existP: null,
|
|
18250
|
+
$root_container: rootContainerP,
|
|
18251
|
+
});
|
|
16891
18252
|
},
|
|
16892
18253
|
});
|
|
16893
18254
|
const render_context = tree_runtime.render_context;
|
|
@@ -16899,23 +18260,24 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16899
18260
|
const iterate_child = tree_runtime.iterate_child;
|
|
16900
18261
|
|
|
16901
18262
|
func.runtime.render.log_tree_debug({
|
|
16902
|
-
SESSION_ID,
|
|
16903
|
-
paramsP,
|
|
18263
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18264
|
+
paramsP: renderer_context.paramsP,
|
|
16904
18265
|
nodeP,
|
|
16905
18266
|
_ds,
|
|
16906
18267
|
});
|
|
16907
18268
|
const special_render = await func.runtime.render.render_special_node({
|
|
16908
|
-
SESSION_ID,
|
|
16909
|
-
$container,
|
|
16910
|
-
$root_container,
|
|
18269
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18270
|
+
$container: renderer_context.$container,
|
|
18271
|
+
$root_container: renderer_context.$root_container,
|
|
18272
|
+
treeP,
|
|
16911
18273
|
nodeP,
|
|
16912
|
-
parent_infoP,
|
|
16913
|
-
paramsP,
|
|
16914
|
-
jobNoP,
|
|
16915
|
-
is_skeleton,
|
|
16916
|
-
keyP,
|
|
16917
|
-
refreshed_ds,
|
|
16918
|
-
parent_nodeP,
|
|
18274
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18275
|
+
paramsP: renderer_context.paramsP,
|
|
18276
|
+
jobNoP: renderer_context.jobNoP,
|
|
18277
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18278
|
+
keyP: renderer_context.keyP,
|
|
18279
|
+
refreshed_ds: renderer_context.refreshed_ds,
|
|
18280
|
+
parent_nodeP: renderer_context.parent_nodeP,
|
|
16919
18281
|
prop,
|
|
16920
18282
|
render_context,
|
|
16921
18283
|
hover_handlers,
|
|
@@ -16923,22 +18285,23 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16923
18285
|
close_modal,
|
|
16924
18286
|
});
|
|
16925
18287
|
if (special_render.handled) {
|
|
16926
|
-
func.runtime?.perf?.increment?.(SESSION_ID, 'render_special_node_hits');
|
|
18288
|
+
func.runtime?.perf?.increment?.(renderer_context.SESSION_ID, 'render_special_node_hits');
|
|
16927
18289
|
return special_render.result;
|
|
16928
18290
|
}
|
|
16929
18291
|
return await func.runtime.render.draw_node({
|
|
16930
|
-
SESSION_ID,
|
|
16931
|
-
$container,
|
|
16932
|
-
$root_container,
|
|
18292
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18293
|
+
$container: renderer_context.$container,
|
|
18294
|
+
$root_container: renderer_context.$root_container,
|
|
18295
|
+
treeP,
|
|
16933
18296
|
nodeP,
|
|
16934
|
-
parent_infoP,
|
|
16935
|
-
paramsP,
|
|
16936
|
-
jobNoP,
|
|
16937
|
-
is_skeleton,
|
|
16938
|
-
keyP,
|
|
16939
|
-
refreshed_ds,
|
|
16940
|
-
parent_nodeP,
|
|
16941
|
-
check_existP,
|
|
18297
|
+
parent_infoP: renderer_context.parent_infoP,
|
|
18298
|
+
paramsP: renderer_context.paramsP,
|
|
18299
|
+
jobNoP: renderer_context.jobNoP,
|
|
18300
|
+
is_skeleton: renderer_context.is_skeleton,
|
|
18301
|
+
keyP: renderer_context.keyP,
|
|
18302
|
+
refreshed_ds: renderer_context.refreshed_ds,
|
|
18303
|
+
parent_nodeP: renderer_context.parent_nodeP,
|
|
18304
|
+
check_existP: renderer_context.check_existP,
|
|
16942
18305
|
prop,
|
|
16943
18306
|
hover_handlers,
|
|
16944
18307
|
include_hover_click,
|
|
@@ -16947,6 +18310,31 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16947
18310
|
} finally {
|
|
16948
18311
|
perf_end?.();
|
|
16949
18312
|
}
|
|
18313
|
+
};
|
|
18314
|
+
func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nodeP, parent_infoP, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $root_container) {
|
|
18315
|
+
if (!nodeP) return;
|
|
18316
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
18317
|
+
SESSION_ID,
|
|
18318
|
+
nodeP,
|
|
18319
|
+
parent_infoP,
|
|
18320
|
+
paramsP,
|
|
18321
|
+
keyP,
|
|
18322
|
+
parent_nodeP,
|
|
18323
|
+
});
|
|
18324
|
+
|
|
18325
|
+
return await func.runtime.render.render_tree(treeP, {
|
|
18326
|
+
SESSION_ID,
|
|
18327
|
+
$container,
|
|
18328
|
+
parent_infoP,
|
|
18329
|
+
paramsP,
|
|
18330
|
+
jobNoP,
|
|
18331
|
+
is_skeleton,
|
|
18332
|
+
keyP,
|
|
18333
|
+
refreshed_ds,
|
|
18334
|
+
parent_nodeP,
|
|
18335
|
+
check_existP,
|
|
18336
|
+
$root_container,
|
|
18337
|
+
});
|
|
16950
18338
|
};
|
|
16951
18339
|
func.runtime = func.runtime || {};
|
|
16952
18340
|
func.runtime.ui = func.runtime.ui || {};
|
|
@@ -18470,6 +19858,7 @@ func.runtime.render.handle_xu_panel_program = async function (options) {
|
|
|
18470
19858
|
parent_infoP: options.parent_infoP,
|
|
18471
19859
|
jobNoP: options.jobNoP,
|
|
18472
19860
|
keyP: options.keyP,
|
|
19861
|
+
treeP: options.treeP,
|
|
18473
19862
|
parent_nodeP: options.parent_nodeP,
|
|
18474
19863
|
prop: options.nodeP.attributes,
|
|
18475
19864
|
$appendToP: $wrapper,
|
|
@@ -22483,6 +23872,12 @@ function xuda(...args) {
|
|
|
22483
23872
|
if (typeof opt !== 'object') {
|
|
22484
23873
|
return console.error('Xuda Error - opt argument is not an object');
|
|
22485
23874
|
}
|
|
23875
|
+
|
|
23876
|
+
if (!opt.ssr_payload && func.runtime.platform.get_window()?.__XUDA_SSR__) {
|
|
23877
|
+
opt.ssr_payload = func.runtime.platform.get_window().__XUDA_SSR__;
|
|
23878
|
+
}
|
|
23879
|
+
func.runtime.render.apply_runtime_bootstrap_defaults(opt);
|
|
23880
|
+
|
|
22486
23881
|
glb.URL_PARAMS = func.common.getJsonFromUrl(platform.get_url_href());
|
|
22487
23882
|
|
|
22488
23883
|
glb.worker_type = 'Worker';
|