@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
package/js/xuda-runtime-slim.js
CHANGED
|
@@ -1779,7 +1779,30 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
1779
1779
|
};
|
|
1780
1780
|
|
|
1781
1781
|
// ── Platform helpers for DOM-independent resource loading ──
|
|
1782
|
-
func.runtime.platform.
|
|
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) {
|
|
1783
1806
|
const doc = func.runtime.platform.get_document();
|
|
1784
1807
|
if (!doc?.createElement || !doc?.head?.appendChild) {
|
|
1785
1808
|
if (callback) {
|
|
@@ -1787,19 +1810,63 @@ func.runtime.platform.load_script = function (url, type, callback) {
|
|
|
1787
1810
|
}
|
|
1788
1811
|
return;
|
|
1789
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
|
+
|
|
1790
1837
|
const script = doc.createElement('script');
|
|
1791
1838
|
script.src = url;
|
|
1792
1839
|
if (type) script.type = type;
|
|
1793
|
-
script
|
|
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
|
+
};
|
|
1794
1852
|
doc.head.appendChild(script);
|
|
1853
|
+
return script;
|
|
1795
1854
|
};
|
|
1796
|
-
func.runtime.platform.load_css = function (href) {
|
|
1855
|
+
func.runtime.platform.load_css = function (href, attributes) {
|
|
1797
1856
|
const doc = func.runtime.platform.get_document();
|
|
1798
1857
|
if (!doc?.createElement || !doc?.head) {
|
|
1799
1858
|
return;
|
|
1800
1859
|
}
|
|
1801
1860
|
try {
|
|
1802
|
-
|
|
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;
|
|
1803
1870
|
} catch (err) {
|
|
1804
1871
|
return;
|
|
1805
1872
|
}
|
|
@@ -1807,7 +1874,9 @@ func.runtime.platform.load_css = function (href) {
|
|
|
1807
1874
|
link.rel = 'stylesheet';
|
|
1808
1875
|
link.type = 'text/css';
|
|
1809
1876
|
link.href = href;
|
|
1877
|
+
func.runtime.platform.apply_element_attributes(link, attributes, ['href']);
|
|
1810
1878
|
doc.head.insertBefore(link, doc.head.firstChild);
|
|
1879
|
+
return link;
|
|
1811
1880
|
};
|
|
1812
1881
|
func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
1813
1882
|
const doc = func.runtime.platform.get_document();
|
|
@@ -2098,6 +2167,147 @@ func.runtime.workers.delete_promise = function (SESSION_ID, worker_id, promise_q
|
|
|
2098
2167
|
delete registry_entry.promise_queue[promise_queue_id];
|
|
2099
2168
|
return true;
|
|
2100
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
|
+
};
|
|
2101
2311
|
func.runtime.render.get_root_data_system = function (SESSION_ID) {
|
|
2102
2312
|
return SESSION_OBJ[SESSION_ID]?.DS_GLB?.[0]?.data_system || null;
|
|
2103
2313
|
};
|
|
@@ -2501,10 +2711,10 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
2501
2711
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
2502
2712
|
break;
|
|
2503
2713
|
case 'css':
|
|
2504
|
-
|
|
2714
|
+
func.runtime.platform.load_css(normalized_resource.src);
|
|
2505
2715
|
break;
|
|
2506
2716
|
case 'module':
|
|
2507
|
-
func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2717
|
+
await func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
2508
2718
|
break;
|
|
2509
2719
|
default:
|
|
2510
2720
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
@@ -3817,30 +4027,715 @@ func.common.get_data_from_websocket = async function (SESSION_ID, serviceP, data
|
|
|
3817
4027
|
// // The .toString(36) method handles the conversion to an alphanumeric representation (0-9, a-z).
|
|
3818
4028
|
// const base36Hash = bigInt.toString(36);
|
|
3819
4029
|
|
|
3820
|
-
// // 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
|
|
3821
|
-
// // For a 64-bit integer, the Base36 representation will be about 13 characters long,
|
|
3822
|
-
// // so slicing is a reliable way to get a fixed length.
|
|
3823
|
-
// const shortHash = base36Hash.slice(0, 10);
|
|
4030
|
+
// // 4. Take the first 10 characters. If it's shorter, it will just return the whole string.
|
|
4031
|
+
// // For a 64-bit integer, the Base36 representation will be about 13 characters long,
|
|
4032
|
+
// // so slicing is a reliable way to get a fixed length.
|
|
4033
|
+
// const shortHash = base36Hash.slice(0, 10);
|
|
4034
|
+
|
|
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
|
+
}
|
|
3824
4636
|
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
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
|
+
};
|
|
3829
4660
|
|
|
3830
|
-
|
|
3831
|
-
|
|
4661
|
+
if (_ds) {
|
|
4662
|
+
_ds.screen_params = paramsP;
|
|
4663
|
+
}
|
|
3832
4664
|
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
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}`);
|
|
3837
4674
|
}
|
|
3838
4675
|
|
|
3839
|
-
|
|
3840
|
-
|
|
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
|
+
};
|
|
3841
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);
|
|
3842
4727
|
|
|
3843
|
-
|
|
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
|
+
};
|
|
3844
4739
|
func.runtime = func.runtime || {};
|
|
3845
4740
|
func.runtime.platform = func.runtime.platform || {};
|
|
3846
4741
|
|
|
@@ -9230,6 +10125,15 @@ func.runtime.ui.ensure_embed_container = function (SESSION_ID) {
|
|
|
9230
10125
|
const $root_element = func.runtime.ui.get_root_element(SESSION_ID);
|
|
9231
10126
|
let $embed_container = func.runtime.ui.find_by_selector($root_element, `#embed_${SESSION_ID}`, true);
|
|
9232
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
|
+
|
|
9233
10137
|
if (!$embed_container.length) {
|
|
9234
10138
|
const embed_node = document.createElement('div');
|
|
9235
10139
|
embed_node.id = 'embed_' + SESSION_ID;
|
|
@@ -9265,12 +10169,44 @@ func.runtime.ui.get_root_tag_name = function () {
|
|
|
9265
10169
|
}
|
|
9266
10170
|
return root_tag_name;
|
|
9267
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
|
+
};
|
|
9268
10198
|
func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params, $callingContainerP, screenId) {
|
|
9269
10199
|
var $dialogDiv;
|
|
9270
10200
|
var $rootFrame;
|
|
10201
|
+
let reused_ssr_host = false;
|
|
9271
10202
|
|
|
9272
10203
|
switch (screen_type) {
|
|
9273
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
|
+
|
|
9274
10210
|
const dialogNode = document.createElement('div');
|
|
9275
10211
|
dialogNode.id = screenId;
|
|
9276
10212
|
dialogNode.setAttribute('ui_engine', UI_FRAMEWORK_INSTALLED);
|
|
@@ -9320,6 +10256,7 @@ func.runtime.ui.create_screen_host = function (SESSION_ID, screen_type, params,
|
|
|
9320
10256
|
return {
|
|
9321
10257
|
$dialogDiv,
|
|
9322
10258
|
$rootFrame,
|
|
10259
|
+
reused_ssr_host,
|
|
9323
10260
|
};
|
|
9324
10261
|
};
|
|
9325
10262
|
func.runtime.ui.find_xu_ui_in_root = function (SESSION_ID, xu_ui_id) {
|
|
@@ -9884,6 +10821,11 @@ func.runtime.ui.build_container_xu_data = function (options) {
|
|
|
9884
10821
|
func.runtime.ui.apply_container_meta = function ($div, options) {
|
|
9885
10822
|
const div_node = func.runtime.ui.get_first_node($div);
|
|
9886
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
|
+
}
|
|
9887
10829
|
const xuData = func.runtime.ui.build_container_xu_data(options);
|
|
9888
10830
|
if (options.parent_infoP?.iterate_info) {
|
|
9889
10831
|
xuData.iterate_info = options.parent_infoP.iterate_info;
|
|
@@ -9978,6 +10920,38 @@ func.runtime.ui.create_container_element = function (div_typeP, attr_str, prop,
|
|
|
9978
10920
|
}
|
|
9979
10921
|
return func.runtime.ui.create_element(div, attr_str);
|
|
9980
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
|
+
};
|
|
9981
10955
|
func.runtime.ui.build_xu_ui_id_seed = function (nodeP, dsSessionP, key_path, currentRecordId) {
|
|
9982
10956
|
const nodeId = nodeP.xu_tree_id || nodeP.id;
|
|
9983
10957
|
const elem_key = `${nodeId}-${key_path}-${currentRecordId}`;
|
|
@@ -10030,7 +11004,11 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
10030
11004
|
try {
|
|
10031
11005
|
const key_path = func.runtime.ui.build_container_key_path(container_xu_data, options.keyP, options.parent_infoP, options.nodeP, options.parent_nodeP);
|
|
10032
11006
|
const elem_key = `${options.nodeP.xu_tree_id || options.nodeP.id}-${key_path}-${currentRecordId}`;
|
|
10033
|
-
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);
|
|
10034
11012
|
const new_ui_id = await func.runtime.ui.generate_xu_ui_id(options.SESSION_ID, options.nodeP, options.$container, options.paramsP, options.keyP, {
|
|
10035
11013
|
container_xu_data,
|
|
10036
11014
|
currentRecordId,
|
|
@@ -10056,9 +11034,10 @@ func.runtime.ui.create_container = async function (options) {
|
|
|
10056
11034
|
parent_infoP: options.parent_infoP,
|
|
10057
11035
|
is_placeholder: options.is_placeholder,
|
|
10058
11036
|
classP: options.classP,
|
|
11037
|
+
treeP: options.treeP,
|
|
10059
11038
|
});
|
|
10060
11039
|
|
|
10061
|
-
if (options.div_typeP !== 'svg') {
|
|
11040
|
+
if (!hydration_candidate && options.div_typeP !== 'svg') {
|
|
10062
11041
|
func.runtime.ui.append_to($div, $appendTo);
|
|
10063
11042
|
}
|
|
10064
11043
|
return $div;
|
|
@@ -12739,9 +13718,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12739
13718
|
|
|
12740
13719
|
const _session = SESSION_OBJ[SESSION_ID];
|
|
12741
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;
|
|
12742
13722
|
|
|
12743
13723
|
const screen_type = source_functionP?.split('_')?.[1];
|
|
12744
|
-
const screenId = (glb.screen_num++).toString();
|
|
13724
|
+
const screenId = ssr_payload?.screenId || (glb.screen_num++).toString();
|
|
12745
13725
|
|
|
12746
13726
|
if (SCREEN_BLOCKER_OBJ[prog_id + (sourceScreenP ? '_' + sourceScreenP : '')]) {
|
|
12747
13727
|
const wait_for_SCREEN_BLOCKER_release = function () {
|
|
@@ -12783,6 +13763,8 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12783
13763
|
call_screen_propertiesP,
|
|
12784
13764
|
parentDataSourceNoP: _session.DS_GLB?.[callingDataSource_objP?.dsSession]?.dsSession || callingDataSource_objP?.parentDataSourceNo || 0,
|
|
12785
13765
|
parameters_raw_obj,
|
|
13766
|
+
containerIdP: ssr_payload?.containerId || null,
|
|
13767
|
+
ssr_payload,
|
|
12786
13768
|
};
|
|
12787
13769
|
|
|
12788
13770
|
const screen_host = func.runtime.ui.create_screen_host(SESSION_ID, screen_type, params, $callingContainerP, screenId);
|
|
@@ -12815,6 +13797,10 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12815
13797
|
func.runtime.ui.set_style($rootFrame, 'display', 'contents');
|
|
12816
13798
|
}
|
|
12817
13799
|
|
|
13800
|
+
if (screen_host.reused_ssr_host && func.runtime.render.is_takeover_mode(_session)) {
|
|
13801
|
+
func.runtime.ui.empty($rootFrame);
|
|
13802
|
+
}
|
|
13803
|
+
|
|
12818
13804
|
if (!is_panelP) func.UI.utils.indicator.screen.busy();
|
|
12819
13805
|
|
|
12820
13806
|
const ret = await func.datasource.create(
|
|
@@ -12856,7 +13842,24 @@ func.runtime.ui.init_screen = async function (options) {
|
|
|
12856
13842
|
}
|
|
12857
13843
|
let node = structuredClone(viewDoc.progUi);
|
|
12858
13844
|
if (!node.length) return console.warn('ui node empty');
|
|
12859
|
-
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
|
+
});
|
|
12860
13863
|
|
|
12861
13864
|
if (!is_panelP) func.UI.utils.indicator.screen.normal();
|
|
12862
13865
|
|
|
@@ -13281,6 +14284,7 @@ func.runtime.ui.render_single_view_node = async function (options) {
|
|
|
13281
14284
|
parent_infoP: options.parent_infoP,
|
|
13282
14285
|
jobNoP: options.jobNoP,
|
|
13283
14286
|
keyP: options.keyP,
|
|
14287
|
+
treeP: options.treeP,
|
|
13284
14288
|
parent_nodeP: options.parent_nodeP,
|
|
13285
14289
|
prop: options.prop,
|
|
13286
14290
|
div_typeP: 'div',
|
|
@@ -13409,6 +14413,7 @@ func.runtime.ui.render_panel_node = async function (options) {
|
|
|
13409
14413
|
parent_infoP: options.parent_infoP,
|
|
13410
14414
|
jobNoP: options.jobNoP,
|
|
13411
14415
|
keyP: options.keyP,
|
|
14416
|
+
treeP: options.treeP,
|
|
13412
14417
|
parent_nodeP: options.parent_nodeP,
|
|
13413
14418
|
prop: options.prop,
|
|
13414
14419
|
$appendToP: $wrapper,
|
|
@@ -13738,6 +14743,14 @@ func.runtime.ui.screen_loading_done = async function (options) {
|
|
|
13738
14743
|
});
|
|
13739
14744
|
|
|
13740
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
|
+
}
|
|
13741
14754
|
func.events.delete_job(options.SESSION_ID, options.jobNoP);
|
|
13742
14755
|
func.UI.utils.screen_blocker(false, options.paramsP.prog_id + (options.paramsP.sourceScreenP ? '_' + options.paramsP.sourceScreenP : ''));
|
|
13743
14756
|
if (_session.prog_id === options.paramsP.prog_id) {
|
|
@@ -15580,6 +16593,9 @@ func.runtime.render.get_screen_context = function (SESSION_ID, $container, param
|
|
|
15580
16593
|
};
|
|
15581
16594
|
func.runtime.render.get_node_attributes = function (nodeP) {
|
|
15582
16595
|
try {
|
|
16596
|
+
if (func.runtime.render.is_tree_node?.(nodeP)) {
|
|
16597
|
+
return nodeP.attributes;
|
|
16598
|
+
}
|
|
15583
16599
|
return nodeP?.attributes;
|
|
15584
16600
|
} catch (error) {
|
|
15585
16601
|
return undefined;
|
|
@@ -15697,6 +16713,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15697
16713
|
parent_infoP: options.parent_infoP,
|
|
15698
16714
|
jobNoP: options.jobNoP,
|
|
15699
16715
|
keyP: options.keyP,
|
|
16716
|
+
treeP: options.treeP,
|
|
15700
16717
|
parent_nodeP: options.parent_nodeP,
|
|
15701
16718
|
prop: options.prop,
|
|
15702
16719
|
div_typeP: options.element,
|
|
@@ -15719,6 +16736,7 @@ func.runtime.render.prepare_draw_context = async function (options) {
|
|
|
15719
16736
|
parent_infoP: options.parent_infoP,
|
|
15720
16737
|
jobNoP: options.jobNoP,
|
|
15721
16738
|
keyP: options.keyP,
|
|
16739
|
+
treeP: options.treeP,
|
|
15722
16740
|
parent_nodeP: options.parent_nodeP,
|
|
15723
16741
|
prop: options.prop,
|
|
15724
16742
|
div_typeP: options.element,
|
|
@@ -16575,11 +17593,16 @@ func.runtime.widgets.render_node = async function (options) {
|
|
|
16575
17593
|
parent_infoP: options.parent_infoP,
|
|
16576
17594
|
jobNoP: options.jobNoP,
|
|
16577
17595
|
keyP: options.keyP,
|
|
17596
|
+
treeP: options.treeP,
|
|
16578
17597
|
parent_nodeP: options.parent_nodeP,
|
|
16579
17598
|
prop: options.prop,
|
|
16580
17599
|
classP: 'widget_wrapper',
|
|
16581
17600
|
});
|
|
16582
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
|
+
|
|
16583
17606
|
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, options.prop);
|
|
16584
17607
|
const { plugin_name, method, propsP, plugin: _plugin } = widget_context;
|
|
16585
17608
|
const report_error = function (descP, warn) {
|
|
@@ -16682,9 +17705,306 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16682
17705
|
|
|
16683
17706
|
// Browser-only special node renderers live here so the core render tree can stay focused.
|
|
16684
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
|
+
|
|
16685
17997
|
func.runtime.render.render_special_node = async function (options) {
|
|
16686
|
-
|
|
16687
|
-
|
|
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;
|
|
16688
18008
|
}
|
|
16689
18009
|
|
|
16690
18010
|
const renderers = {
|
|
@@ -16694,6 +18014,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16694
18014
|
SESSION_ID: options.SESSION_ID,
|
|
16695
18015
|
$container: options.$container,
|
|
16696
18016
|
$root_container: options.$root_container,
|
|
18017
|
+
treeP,
|
|
16697
18018
|
nodeP: options.nodeP,
|
|
16698
18019
|
parent_infoP: options.parent_infoP,
|
|
16699
18020
|
paramsP: options.paramsP,
|
|
@@ -16710,6 +18031,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16710
18031
|
SESSION_ID: options.SESSION_ID,
|
|
16711
18032
|
$container: options.$container,
|
|
16712
18033
|
$root_container: options.$root_container,
|
|
18034
|
+
treeP,
|
|
16713
18035
|
nodeP: options.nodeP,
|
|
16714
18036
|
parent_infoP: options.parent_infoP,
|
|
16715
18037
|
paramsP: options.paramsP,
|
|
@@ -16729,6 +18051,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16729
18051
|
SESSION_ID: options.SESSION_ID,
|
|
16730
18052
|
$container: options.$container,
|
|
16731
18053
|
$root_container: options.$root_container,
|
|
18054
|
+
treeP,
|
|
16732
18055
|
nodeP: options.nodeP,
|
|
16733
18056
|
parent_infoP: options.parent_infoP,
|
|
16734
18057
|
paramsP: options.paramsP,
|
|
@@ -16745,6 +18068,7 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16745
18068
|
SESSION_ID: options.SESSION_ID,
|
|
16746
18069
|
$container: options.$container,
|
|
16747
18070
|
$root_container: options.$root_container,
|
|
18071
|
+
treeP,
|
|
16748
18072
|
nodeP: options.nodeP,
|
|
16749
18073
|
parent_infoP: options.parent_infoP,
|
|
16750
18074
|
paramsP: options.paramsP,
|
|
@@ -16756,9 +18080,24 @@ func.runtime.render.render_special_node = async function (options) {
|
|
|
16756
18080
|
refreshed_ds: options.refreshed_ds,
|
|
16757
18081
|
});
|
|
16758
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
|
+
},
|
|
16759
18098
|
};
|
|
16760
18099
|
|
|
16761
|
-
const renderer = renderers[
|
|
18100
|
+
const renderer = renderers[normalized_render_tag_name];
|
|
16762
18101
|
if (!renderer) {
|
|
16763
18102
|
return { handled: false };
|
|
16764
18103
|
}
|
|
@@ -16872,8 +18211,9 @@ func.runtime.widgets = func.runtime.widgets || {};
|
|
|
16872
18211
|
// Browser-only render tree entrypoints live here so draw/cache helpers can stay focused.
|
|
16873
18212
|
|
|
16874
18213
|
func.runtime.render.create_tree_runtime = function (options) {
|
|
18214
|
+
const render_node = options.nodeP || func.runtime.render.get_tree_source_node(options.treeP);
|
|
16875
18215
|
const render_context = func.runtime.render.get_screen_context(options.SESSION_ID, options.$container, options.paramsP, options.is_skeleton);
|
|
16876
|
-
const prop = func.runtime.render.get_node_attributes(options.
|
|
18216
|
+
const prop = func.runtime.render.get_node_attributes(options.treeP || render_node);
|
|
16877
18217
|
const is_mobile = render_context.is_mobile ? true : false;
|
|
16878
18218
|
const hover_handlers = func.runtime.render.create_hover_handlers({
|
|
16879
18219
|
SESSION_ID: options.SESSION_ID,
|
|
@@ -16888,13 +18228,22 @@ func.runtime.render.create_tree_runtime = function (options) {
|
|
|
16888
18228
|
return await func.runtime.ui.close_modal_session(options.SESSION_ID, modal_id);
|
|
16889
18229
|
};
|
|
16890
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
|
+
});
|
|
16891
18240
|
return await func.runtime.render.iterate_children({
|
|
16892
18241
|
$divP,
|
|
16893
|
-
nodeP,
|
|
18242
|
+
nodeP: child_tree,
|
|
16894
18243
|
is_mobile,
|
|
16895
18244
|
before_record_function,
|
|
16896
18245
|
render_child: async function (key, child) {
|
|
16897
|
-
await options.render_child($divP, child, parent_infoP, key,
|
|
18246
|
+
await options.render_child($divP, child, parent_infoP, key, render_node, $root_container);
|
|
16898
18247
|
},
|
|
16899
18248
|
});
|
|
16900
18249
|
};
|
|
@@ -16924,7 +18273,7 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16924
18273
|
check_existP: options.check_existP,
|
|
16925
18274
|
$root_container: options.$root_container,
|
|
16926
18275
|
prop: options.prop,
|
|
16927
|
-
element: options.nodeP.tagName,
|
|
18276
|
+
element: options.treeP?.tagName || options.nodeP.tagName,
|
|
16928
18277
|
hover_handlers: options.hover_handlers,
|
|
16929
18278
|
include_hover_click: options.include_hover_click,
|
|
16930
18279
|
iterate_child: options.iterate_child,
|
|
@@ -16947,21 +18296,33 @@ func.runtime.render.draw_node = async function (options) {
|
|
|
16947
18296
|
nodeP: options.nodeP,
|
|
16948
18297
|
});
|
|
16949
18298
|
};
|
|
16950
|
-
func.runtime.render.
|
|
16951
|
-
if (!
|
|
16952
|
-
const
|
|
16953
|
-
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');
|
|
16954
18304
|
try {
|
|
16955
18305
|
const tree_runtime = func.runtime.render.create_tree_runtime({
|
|
16956
|
-
SESSION_ID,
|
|
16957
|
-
$container,
|
|
18306
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18307
|
+
$container: renderer_context.$container,
|
|
18308
|
+
treeP,
|
|
16958
18309
|
nodeP,
|
|
16959
|
-
parent_infoP,
|
|
16960
|
-
paramsP,
|
|
16961
|
-
jobNoP,
|
|
16962
|
-
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,
|
|
16963
18315
|
render_child: async function ($divP, child, parent_infoP, key, parentNodeP, rootContainerP) {
|
|
16964
|
-
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
|
+
});
|
|
16965
18326
|
},
|
|
16966
18327
|
});
|
|
16967
18328
|
const render_context = tree_runtime.render_context;
|
|
@@ -16973,23 +18334,24 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16973
18334
|
const iterate_child = tree_runtime.iterate_child;
|
|
16974
18335
|
|
|
16975
18336
|
func.runtime.render.log_tree_debug({
|
|
16976
|
-
SESSION_ID,
|
|
16977
|
-
paramsP,
|
|
18337
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18338
|
+
paramsP: renderer_context.paramsP,
|
|
16978
18339
|
nodeP,
|
|
16979
18340
|
_ds,
|
|
16980
18341
|
});
|
|
16981
18342
|
const special_render = await func.runtime.render.render_special_node({
|
|
16982
|
-
SESSION_ID,
|
|
16983
|
-
$container,
|
|
16984
|
-
$root_container,
|
|
18343
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18344
|
+
$container: renderer_context.$container,
|
|
18345
|
+
$root_container: renderer_context.$root_container,
|
|
18346
|
+
treeP,
|
|
16985
18347
|
nodeP,
|
|
16986
|
-
parent_infoP,
|
|
16987
|
-
paramsP,
|
|
16988
|
-
jobNoP,
|
|
16989
|
-
is_skeleton,
|
|
16990
|
-
keyP,
|
|
16991
|
-
refreshed_ds,
|
|
16992
|
-
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,
|
|
16993
18355
|
prop,
|
|
16994
18356
|
render_context,
|
|
16995
18357
|
hover_handlers,
|
|
@@ -16997,22 +18359,23 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
16997
18359
|
close_modal,
|
|
16998
18360
|
});
|
|
16999
18361
|
if (special_render.handled) {
|
|
17000
|
-
func.runtime?.perf?.increment?.(SESSION_ID, 'render_special_node_hits');
|
|
18362
|
+
func.runtime?.perf?.increment?.(renderer_context.SESSION_ID, 'render_special_node_hits');
|
|
17001
18363
|
return special_render.result;
|
|
17002
18364
|
}
|
|
17003
18365
|
return await func.runtime.render.draw_node({
|
|
17004
|
-
SESSION_ID,
|
|
17005
|
-
$container,
|
|
17006
|
-
$root_container,
|
|
18366
|
+
SESSION_ID: renderer_context.SESSION_ID,
|
|
18367
|
+
$container: renderer_context.$container,
|
|
18368
|
+
$root_container: renderer_context.$root_container,
|
|
18369
|
+
treeP,
|
|
17007
18370
|
nodeP,
|
|
17008
|
-
parent_infoP,
|
|
17009
|
-
paramsP,
|
|
17010
|
-
jobNoP,
|
|
17011
|
-
is_skeleton,
|
|
17012
|
-
keyP,
|
|
17013
|
-
refreshed_ds,
|
|
17014
|
-
parent_nodeP,
|
|
17015
|
-
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,
|
|
17016
18379
|
prop,
|
|
17017
18380
|
hover_handlers,
|
|
17018
18381
|
include_hover_click,
|
|
@@ -17021,6 +18384,31 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
|
|
|
17021
18384
|
} finally {
|
|
17022
18385
|
perf_end?.();
|
|
17023
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
|
+
});
|
|
17024
18412
|
};
|
|
17025
18413
|
func.runtime = func.runtime || {};
|
|
17026
18414
|
func.runtime.ui = func.runtime.ui || {};
|
|
@@ -18544,6 +19932,7 @@ func.runtime.render.handle_xu_panel_program = async function (options) {
|
|
|
18544
19932
|
parent_infoP: options.parent_infoP,
|
|
18545
19933
|
jobNoP: options.jobNoP,
|
|
18546
19934
|
keyP: options.keyP,
|
|
19935
|
+
treeP: options.treeP,
|
|
18547
19936
|
parent_nodeP: options.parent_nodeP,
|
|
18548
19937
|
prop: options.nodeP.attributes,
|
|
18549
19938
|
$appendToP: $wrapper,
|
|
@@ -22557,6 +23946,12 @@ function xuda(...args) {
|
|
|
22557
23946
|
if (typeof opt !== 'object') {
|
|
22558
23947
|
return console.error('Xuda Error - opt argument is not an object');
|
|
22559
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
|
+
|
|
22560
23955
|
glb.URL_PARAMS = func.common.getJsonFromUrl(platform.get_url_href());
|
|
22561
23956
|
|
|
22562
23957
|
glb.worker_type = 'Worker';
|