@xuda.io/runtime-bundle 1.0.1435 → 1.0.1437
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/modules/xuda-event-ui-elements-module.esm.js +1 -1
- package/js/modules/xuda-event-ui-elements-module.esm.min.js +1 -1
- package/js/modules/xuda-live-preview-module.esm.js +1 -1
- package/js/modules/xuda-live-preview-module.esm.min.js +1 -1
- package/js/xuda-runtime-bundle.js +1624 -203
- package/js/xuda-runtime-bundle.min.js +3 -3
- package/js/xuda-runtime-slim.js +1624 -203
- package/js/xuda-runtime-slim.min.es.js +1624 -203
- package/js/xuda-runtime-slim.min.js +3 -3
- package/js/xuda-server-bundle.min.mjs +1 -1
- package/js/xuda-server-bundle.mjs +1031 -108
- package/js/xuda-worker-bundle.js +1031 -108
- package/js/xuda-worker-bundle.min.js +1 -1
- package/js/xuda_common-bundle.js +346 -108
- package/js/xuda_common-bundle.min.js +1 -1
- package/package.json +1 -1
package/js/xuda-worker-bundle.js
CHANGED
|
@@ -5,49 +5,6 @@ if (typeof IS_DOCKER === 'undefined' || typeof IS_PROCESS_SERVER === 'undefined'
|
|
|
5
5
|
var DOCS_OBJ = {};
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
// Minimal jQuery shim for plugins that still reference $
|
|
9
|
-
if (typeof $ === 'undefined' && typeof document !== 'undefined') {
|
|
10
|
-
var $ = function (selector) {
|
|
11
|
-
var nodes = typeof selector === 'string'
|
|
12
|
-
? Array.from(document.querySelectorAll(selector))
|
|
13
|
-
: selector?.nodeType ? [selector] : (selector?.length ? Array.from(selector) : []);
|
|
14
|
-
var obj = {
|
|
15
|
-
0: nodes[0], length: nodes.length,
|
|
16
|
-
toArray: function () { return nodes.slice(); },
|
|
17
|
-
find: function (s) { var r = []; for (var i = 0; i < nodes.length; i++) { r.push.apply(r, Array.from(nodes[i].querySelectorAll(s))); } return $(r); },
|
|
18
|
-
each: function (fn) { for (var i = 0; i < nodes.length; i++) { fn.call(nodes[i], i, nodes[i]); } return obj; },
|
|
19
|
-
on: function (ev, fn) { for (var i = 0; i < nodes.length; i++) nodes[i].addEventListener(ev, fn); return obj; },
|
|
20
|
-
off: function (ev, fn) { for (var i = 0; i < nodes.length; i++) nodes[i].removeEventListener(ev, fn); return obj; },
|
|
21
|
-
addClass: function (c) { for (var i = 0; i < nodes.length; i++) nodes[i].classList?.add(c); return obj; },
|
|
22
|
-
removeClass: function (c) { for (var i = 0; i < nodes.length; i++) nodes[i].classList?.remove(c); return obj; },
|
|
23
|
-
hasClass: function (c) { return nodes[0]?.classList?.contains(c) || false; },
|
|
24
|
-
attr: function (k, v) { if (typeof v === 'undefined') return nodes[0]?.getAttribute(k); for (var i = 0; i < nodes.length; i++) nodes[i].setAttribute(k, v); return obj; },
|
|
25
|
-
css: function (k, v) { for (var i = 0; i < nodes.length; i++) nodes[i].style[k] = v; return obj; },
|
|
26
|
-
data: function () { return nodes[0]?.__xuData || (nodes[0] ? (nodes[0].__xuData = {}) : {}); },
|
|
27
|
-
val: function (v) { if (typeof v === 'undefined') return nodes[0]?.value; for (var i = 0; i < nodes.length; i++) nodes[i].value = v; return obj; },
|
|
28
|
-
html: function (v) { if (typeof v === 'undefined') return nodes[0]?.innerHTML; for (var i = 0; i < nodes.length; i++) nodes[i].innerHTML = v; return obj; },
|
|
29
|
-
text: function (v) { if (typeof v === 'undefined') return nodes[0]?.textContent; for (var i = 0; i < nodes.length; i++) nodes[i].textContent = v; return obj; },
|
|
30
|
-
show: function () { for (var i = 0; i < nodes.length; i++) nodes[i].style.display = ''; return obj; },
|
|
31
|
-
hide: function () { for (var i = 0; i < nodes.length; i++) nodes[i].style.display = 'none'; return obj; },
|
|
32
|
-
remove: function () { for (var i = 0; i < nodes.length; i++) nodes[i].remove?.(); return obj; },
|
|
33
|
-
empty: function () { for (var i = 0; i < nodes.length; i++) nodes[i].innerHTML = ''; return obj; },
|
|
34
|
-
append: function (c) { var n = c?.nodeType ? c : c?.[0]; if (n && nodes[0]) nodes[0].appendChild(n); return obj; },
|
|
35
|
-
parent: function () { return $(nodes[0]?.parentElement ? [nodes[0].parentElement] : []); },
|
|
36
|
-
children: function () { return $(nodes[0] ? Array.from(nodes[0].children) : []); },
|
|
37
|
-
trigger: function (ev, d) { for (var i = 0; i < nodes.length; i++) nodes[i].dispatchEvent(new CustomEvent(ev, { detail: d })); return obj; },
|
|
38
|
-
is: function (s) { return nodes[0]?.matches?.(s) || false; },
|
|
39
|
-
prop: function (k, v) { if (typeof v === 'undefined') return nodes[0]?.[k]; for (var i = 0; i < nodes.length; i++) nodes[i][k] = v; return obj; },
|
|
40
|
-
unbind: function () { return obj; },
|
|
41
|
-
clone: function () { return $(nodes[0]?.cloneNode(true) ? [nodes[0].cloneNode(true)] : []); },
|
|
42
|
-
};
|
|
43
|
-
obj[Symbol.iterator] = function () { var i = 0; return { next: function () { return i < nodes.length ? { value: nodes[i++], done: false } : { done: true }; } }; };
|
|
44
|
-
return obj;
|
|
45
|
-
};
|
|
46
|
-
$.each = function (o, fn) { if (Array.isArray(o)) { for (var i = 0; i < o.length; i++) fn(i, o[i]); } else { Object.keys(o || {}).forEach(function (k) { fn(k, o[k]); }); } };
|
|
47
|
-
$.cookie = function () { return null; };
|
|
48
|
-
var jQuery = $;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
8
|
var glb = {};
|
|
52
9
|
var func = {};
|
|
53
10
|
func.UI = {};
|
|
@@ -121,23 +78,27 @@ glb.PROTECTED_VARS = ['_NULL', '_THIS', '_FOR_KEY', '_FOR_VAL', '_ROWNO', '_ROWI
|
|
|
121
78
|
|
|
122
79
|
func.common = {};
|
|
123
80
|
func.runtime.platform = {
|
|
81
|
+
get_global: function (name) {
|
|
82
|
+
try {
|
|
83
|
+
if (typeof globalThis === 'undefined') {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return globalThis?.[name] || null;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
124
91
|
has_window: function () {
|
|
125
|
-
return
|
|
92
|
+
return !!func.runtime.platform.get_window();
|
|
126
93
|
},
|
|
127
94
|
has_document: function () {
|
|
128
|
-
return
|
|
95
|
+
return !!func.runtime.platform.get_document();
|
|
129
96
|
},
|
|
130
97
|
get_window: function () {
|
|
131
|
-
|
|
132
|
-
return window;
|
|
133
|
-
}
|
|
134
|
-
return null;
|
|
98
|
+
return func.runtime.platform.get_global('window');
|
|
135
99
|
},
|
|
136
100
|
get_document: function () {
|
|
137
|
-
|
|
138
|
-
return document;
|
|
139
|
-
}
|
|
140
|
-
return null;
|
|
101
|
+
return func.runtime.platform.get_global('document');
|
|
141
102
|
},
|
|
142
103
|
get_location: function () {
|
|
143
104
|
const win = func.runtime.platform.get_window();
|
|
@@ -148,27 +109,23 @@ func.runtime.platform = {
|
|
|
148
109
|
if (win?.navigator) {
|
|
149
110
|
return win.navigator;
|
|
150
111
|
}
|
|
151
|
-
|
|
152
|
-
return navigator;
|
|
153
|
-
}
|
|
154
|
-
return null;
|
|
112
|
+
return func.runtime.platform.get_global('navi' + 'gator');
|
|
155
113
|
},
|
|
156
114
|
is_html_element: function (value) {
|
|
157
|
-
|
|
115
|
+
const html_element = func.runtime.platform.get_global('HTML' + 'Element');
|
|
116
|
+
if (typeof html_element !== 'function') {
|
|
158
117
|
return false;
|
|
159
118
|
}
|
|
160
|
-
return value instanceof
|
|
119
|
+
return value instanceof html_element;
|
|
161
120
|
},
|
|
162
121
|
get_storage: function (type) {
|
|
163
122
|
const win = func.runtime.platform.get_window();
|
|
123
|
+
const storage_key = type === 'session' ? 'session' + 'Storage' : 'local' + 'Storage';
|
|
164
124
|
try {
|
|
165
125
|
if (!win) {
|
|
166
126
|
return null;
|
|
167
127
|
}
|
|
168
|
-
|
|
169
|
-
return win.sessionStorage || null;
|
|
170
|
-
}
|
|
171
|
-
return win.localStorage || null;
|
|
128
|
+
return win?.[storage_key] || null;
|
|
172
129
|
} catch (error) {
|
|
173
130
|
return null;
|
|
174
131
|
}
|
|
@@ -325,9 +282,8 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
325
282
|
handlers[i](data);
|
|
326
283
|
}
|
|
327
284
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
document.dispatchEvent(new CustomEvent(name, { detail: Array.isArray(data) ? data : [data] }));
|
|
285
|
+
if (typeof func.runtime.platform.dispatch_document_event === 'function') {
|
|
286
|
+
func.runtime.platform.dispatch_document_event(name, data);
|
|
331
287
|
}
|
|
332
288
|
} finally {
|
|
333
289
|
func.runtime.platform._emitting[name] = false;
|
|
@@ -335,35 +291,111 @@ func.runtime.platform.emit = function (name, data) {
|
|
|
335
291
|
};
|
|
336
292
|
|
|
337
293
|
// ── Platform helpers for DOM-independent resource loading ──
|
|
338
|
-
func.runtime.platform.
|
|
339
|
-
if (
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
294
|
+
func.runtime.platform.apply_element_attributes = function (node, attributes, excluded_keys = []) {
|
|
295
|
+
if (!node?.setAttribute || !attributes) {
|
|
296
|
+
return node;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const excluded = new Set(excluded_keys || []);
|
|
300
|
+
const attr_keys = Object.keys(attributes);
|
|
301
|
+
for (let index = 0; index < attr_keys.length; index++) {
|
|
302
|
+
const key = attr_keys[index];
|
|
303
|
+
if (!key || excluded.has(key)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const value = attributes[key];
|
|
308
|
+
if (value === false || typeof value === 'undefined') {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
node.setAttribute(key, value === null ? '' : `${value}`);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return node;
|
|
316
|
+
};
|
|
317
|
+
func.runtime.platform.load_script = function (url, type, callback, attributes) {
|
|
318
|
+
const doc = func.runtime.platform.get_document();
|
|
319
|
+
if (!doc?.createElement || !doc?.head?.appendChild) {
|
|
320
|
+
if (callback) {
|
|
321
|
+
callback();
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const find_existing_script = function () {
|
|
326
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
327
|
+
const scripts = doc.querySelectorAll ? Array.from(doc.querySelectorAll('script')) : [];
|
|
328
|
+
return scripts.find(function (script) {
|
|
329
|
+
if (asset_key && script.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
return !!(url && script.getAttribute('src') === url);
|
|
333
|
+
}) || null;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const existing_script = find_existing_script();
|
|
337
|
+
if (existing_script) {
|
|
338
|
+
if (callback) {
|
|
339
|
+
if (existing_script.getAttribute('data-xuda-loaded') === 'true' || !url) {
|
|
340
|
+
callback();
|
|
341
|
+
} else {
|
|
342
|
+
existing_script.addEventListener('load', callback, { once: true });
|
|
343
|
+
existing_script.addEventListener('error', callback, { once: true });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return existing_script;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const script = doc.createElement('script');
|
|
350
|
+
script.src = url;
|
|
351
|
+
if (type) script.type = type;
|
|
352
|
+
func.runtime.platform.apply_element_attributes(script, attributes, ['src', 'type']);
|
|
353
|
+
script.onload = function () {
|
|
354
|
+
script.setAttribute('data-xuda-loaded', 'true');
|
|
355
|
+
if (callback) {
|
|
356
|
+
callback();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
script.onerror = function () {
|
|
360
|
+
if (callback) {
|
|
361
|
+
callback();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
doc.head.appendChild(script);
|
|
365
|
+
return script;
|
|
366
|
+
};
|
|
367
|
+
func.runtime.platform.load_css = function (href, attributes) {
|
|
368
|
+
const doc = func.runtime.platform.get_document();
|
|
369
|
+
if (!doc?.createElement || !doc?.head) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
351
372
|
try {
|
|
352
|
-
|
|
373
|
+
const asset_key = attributes?.['data-xuda-asset-key'];
|
|
374
|
+
const existing_links = doc.querySelectorAll ? Array.from(doc.querySelectorAll('link')) : [];
|
|
375
|
+
const existing = existing_links.find(function (link) {
|
|
376
|
+
if (asset_key && link.getAttribute('data-xuda-asset-key') === asset_key) {
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
return !!(href && link.getAttribute('href') === href);
|
|
380
|
+
});
|
|
381
|
+
if (existing) return existing;
|
|
353
382
|
} catch (err) {
|
|
354
383
|
return;
|
|
355
384
|
}
|
|
356
|
-
const link =
|
|
385
|
+
const link = doc.createElement('link');
|
|
357
386
|
link.rel = 'stylesheet';
|
|
358
387
|
link.type = 'text/css';
|
|
359
388
|
link.href = href;
|
|
360
|
-
|
|
389
|
+
func.runtime.platform.apply_element_attributes(link, attributes, ['href']);
|
|
390
|
+
doc.head.insertBefore(link, doc.head.firstChild);
|
|
391
|
+
return link;
|
|
361
392
|
};
|
|
362
393
|
func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
363
|
-
|
|
394
|
+
const doc = func.runtime.platform.get_document();
|
|
395
|
+
if (!doc?.getElementsByTagName) return;
|
|
364
396
|
const tagName = filetype === 'js' ? 'script' : filetype === 'css' ? 'link' : 'none';
|
|
365
397
|
const attr = filetype === 'js' ? 'src' : filetype === 'css' ? 'href' : 'none';
|
|
366
|
-
const elements =
|
|
398
|
+
const elements = doc.getElementsByTagName(tagName);
|
|
367
399
|
for (let i = elements.length - 1; i >= 0; i--) {
|
|
368
400
|
if (elements[i] && elements[i].getAttribute(attr) != null && elements[i].getAttribute(attr).indexOf(filename) !== -1) {
|
|
369
401
|
elements[i].parentNode.removeChild(elements[i]);
|
|
@@ -371,15 +403,17 @@ func.runtime.platform.remove_js_css = function (filename, filetype) {
|
|
|
371
403
|
}
|
|
372
404
|
};
|
|
373
405
|
func.runtime.platform.inject_css = function (cssText) {
|
|
374
|
-
|
|
375
|
-
|
|
406
|
+
const doc = func.runtime.platform.get_document();
|
|
407
|
+
if (!doc?.createElement || !doc?.head?.appendChild || !cssText) return;
|
|
408
|
+
const style = doc.createElement('style');
|
|
376
409
|
style.type = 'text/css';
|
|
377
410
|
style.textContent = cssText;
|
|
378
|
-
|
|
411
|
+
doc.head.appendChild(style);
|
|
379
412
|
};
|
|
380
413
|
func.runtime.platform.set_title = function (title) {
|
|
381
|
-
|
|
382
|
-
|
|
414
|
+
const doc = func.runtime.platform.get_document();
|
|
415
|
+
if (doc) {
|
|
416
|
+
doc.title = title;
|
|
383
417
|
}
|
|
384
418
|
};
|
|
385
419
|
func.runtime.platform.set_cursor = function (element, cursor) {
|
|
@@ -645,6 +679,147 @@ func.runtime.workers.delete_promise = function (SESSION_ID, worker_id, promise_q
|
|
|
645
679
|
delete registry_entry.promise_queue[promise_queue_id];
|
|
646
680
|
return true;
|
|
647
681
|
};
|
|
682
|
+
func.runtime.render.clone_runtime_options = function (value) {
|
|
683
|
+
if (typeof structuredClone === 'function') {
|
|
684
|
+
try {
|
|
685
|
+
return structuredClone(value);
|
|
686
|
+
} catch (_) {}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (Array.isArray(value)) {
|
|
690
|
+
return value.map(function (item) {
|
|
691
|
+
return func.runtime.render.clone_runtime_options(item);
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (value && typeof value === 'object') {
|
|
696
|
+
const cloned = {};
|
|
697
|
+
const keys = Object.keys(value);
|
|
698
|
+
for (let index = 0; index < keys.length; index++) {
|
|
699
|
+
const key = keys[index];
|
|
700
|
+
cloned[key] = func.runtime.render.clone_runtime_options(value[key]);
|
|
701
|
+
}
|
|
702
|
+
return cloned;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
return value;
|
|
706
|
+
};
|
|
707
|
+
func.runtime.render.normalize_runtime_bootstrap = function (raw_options = {}) {
|
|
708
|
+
const options = raw_options || {};
|
|
709
|
+
let app_computing_mode = options.app_computing_mode || '';
|
|
710
|
+
let app_render_mode = options.app_render_mode || '';
|
|
711
|
+
let app_client_activation = options.app_client_activation || '';
|
|
712
|
+
let ssr_payload = options.ssr_payload || null;
|
|
713
|
+
|
|
714
|
+
if (typeof ssr_payload === 'string') {
|
|
715
|
+
try {
|
|
716
|
+
ssr_payload = JSON.parse(ssr_payload);
|
|
717
|
+
} catch (_) {
|
|
718
|
+
ssr_payload = null;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
723
|
+
ssr_payload = func.runtime.render.clone_runtime_options(ssr_payload);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (!app_computing_mode) {
|
|
727
|
+
if (app_render_mode === 'ssr_first_page' || app_render_mode === 'ssr_full') {
|
|
728
|
+
app_computing_mode = 'server';
|
|
729
|
+
} else {
|
|
730
|
+
app_computing_mode = 'main';
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
switch (app_computing_mode) {
|
|
735
|
+
case 'main':
|
|
736
|
+
app_render_mode = 'csr';
|
|
737
|
+
app_client_activation = 'none';
|
|
738
|
+
break;
|
|
739
|
+
|
|
740
|
+
case 'worker':
|
|
741
|
+
app_render_mode = 'csr';
|
|
742
|
+
app_client_activation = 'none';
|
|
743
|
+
break;
|
|
744
|
+
|
|
745
|
+
default:
|
|
746
|
+
app_computing_mode = 'server';
|
|
747
|
+
if (app_render_mode !== 'ssr_full') {
|
|
748
|
+
app_render_mode = 'ssr_first_page';
|
|
749
|
+
}
|
|
750
|
+
app_client_activation = app_render_mode === 'ssr_full' ? 'hydrate' : 'takeover';
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
if (ssr_payload && typeof ssr_payload === 'object') {
|
|
755
|
+
if (!ssr_payload.app_render_mode) {
|
|
756
|
+
ssr_payload.app_render_mode = app_render_mode;
|
|
757
|
+
}
|
|
758
|
+
if (!ssr_payload.app_client_activation) {
|
|
759
|
+
ssr_payload.app_client_activation = app_client_activation;
|
|
760
|
+
}
|
|
761
|
+
if (!ssr_payload.app_computing_mode) {
|
|
762
|
+
ssr_payload.app_computing_mode = app_computing_mode;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
return {
|
|
767
|
+
app_computing_mode,
|
|
768
|
+
app_render_mode,
|
|
769
|
+
app_client_activation,
|
|
770
|
+
ssr_payload,
|
|
771
|
+
};
|
|
772
|
+
};
|
|
773
|
+
func.runtime.render.apply_runtime_bootstrap_defaults = function (target = {}) {
|
|
774
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target);
|
|
775
|
+
target.app_computing_mode = normalized.app_computing_mode;
|
|
776
|
+
target.app_render_mode = normalized.app_render_mode;
|
|
777
|
+
target.app_client_activation = normalized.app_client_activation;
|
|
778
|
+
target.ssr_payload = normalized.ssr_payload;
|
|
779
|
+
return normalized;
|
|
780
|
+
};
|
|
781
|
+
func.runtime.render.is_server_render_mode = function (target = {}) {
|
|
782
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
783
|
+
return normalized.app_computing_mode === 'server' && normalized.app_render_mode !== 'csr';
|
|
784
|
+
};
|
|
785
|
+
func.runtime.render.is_takeover_mode = function (target = {}) {
|
|
786
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
787
|
+
return normalized.app_client_activation === 'takeover';
|
|
788
|
+
};
|
|
789
|
+
func.runtime.render.is_hydration_mode = function (target = {}) {
|
|
790
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap(target?.opt || target);
|
|
791
|
+
return normalized.app_client_activation === 'hydrate';
|
|
792
|
+
};
|
|
793
|
+
func.runtime.render.get_ssr_payload = function (target = {}) {
|
|
794
|
+
if (target?.opt?.ssr_payload) {
|
|
795
|
+
return target.opt.ssr_payload;
|
|
796
|
+
}
|
|
797
|
+
if (target?.ssr_payload) {
|
|
798
|
+
return target.ssr_payload;
|
|
799
|
+
}
|
|
800
|
+
const win = func.runtime.platform.get_window();
|
|
801
|
+
return win?.__XUDA_SSR__ || null;
|
|
802
|
+
};
|
|
803
|
+
func.runtime.render.should_use_ssr_payload = function (SESSION_ID, paramsP) {
|
|
804
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
805
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
806
|
+
if (!payload || payload._consumed) {
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
809
|
+
if (paramsP?.prog_id && payload.prog_id && payload.prog_id !== paramsP.prog_id) {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
return true;
|
|
813
|
+
};
|
|
814
|
+
func.runtime.render.mark_ssr_payload_consumed = function (SESSION_ID) {
|
|
815
|
+
const session = SESSION_OBJ?.[SESSION_ID];
|
|
816
|
+
const payload = func.runtime.render.get_ssr_payload(session);
|
|
817
|
+
if (!payload || typeof payload !== 'object') {
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
payload._consumed = true;
|
|
821
|
+
return true;
|
|
822
|
+
};
|
|
648
823
|
func.runtime.render.get_root_data_system = function (SESSION_ID) {
|
|
649
824
|
return SESSION_OBJ[SESSION_ID]?.DS_GLB?.[0]?.data_system || null;
|
|
650
825
|
};
|
|
@@ -1048,10 +1223,10 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
1048
1223
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
1049
1224
|
break;
|
|
1050
1225
|
case 'css':
|
|
1051
|
-
|
|
1226
|
+
func.runtime.platform.load_css(normalized_resource.src);
|
|
1052
1227
|
break;
|
|
1053
1228
|
case 'module':
|
|
1054
|
-
func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
1229
|
+
await func.utils.load_js_on_demand(normalized_resource.src, 'module');
|
|
1055
1230
|
break;
|
|
1056
1231
|
default:
|
|
1057
1232
|
await func.utils.load_js_on_demand(normalized_resource.src);
|
|
@@ -1067,12 +1242,36 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
|
|
|
1067
1242
|
func.runtime.resources.get_plugin_manifest_entry = function (_session, plugin_name) {
|
|
1068
1243
|
return APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name] || null;
|
|
1069
1244
|
};
|
|
1070
|
-
func.runtime.resources.
|
|
1245
|
+
func.runtime.resources.get_plugin_resource_candidates = function (_session, plugin, resource) {
|
|
1071
1246
|
const manifest_entry = plugin?.manifest?.[resource];
|
|
1072
|
-
|
|
1247
|
+
const default_path = `${manifest_entry?.dist ? 'dist/' : ''}${resource}`;
|
|
1248
|
+
const candidates = [];
|
|
1249
|
+
if (_session?.worker_type === 'Dev' && manifest_entry?.dist && /\.mjs$/.test(resource)) {
|
|
1250
|
+
candidates.push(`src/${resource}`);
|
|
1251
|
+
}
|
|
1252
|
+
candidates.push(default_path);
|
|
1253
|
+
return Array.from(new Set(candidates.filter(Boolean)));
|
|
1254
|
+
};
|
|
1255
|
+
func.runtime.resources.get_plugin_module_path = function (plugin, resource, _session) {
|
|
1256
|
+
return func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource)[0] || resource;
|
|
1073
1257
|
};
|
|
1074
1258
|
func.runtime.resources.get_plugin_module_url = async function (SESSION_ID, plugin_name, plugin, resource) {
|
|
1075
|
-
|
|
1259
|
+
const _session = SESSION_OBJ[SESSION_ID];
|
|
1260
|
+
return await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, func.runtime.resources.get_plugin_module_path(plugin, resource, _session));
|
|
1261
|
+
};
|
|
1262
|
+
func.runtime.resources.import_plugin_module = async function (SESSION_ID, plugin_name, plugin, resource) {
|
|
1263
|
+
const _session = SESSION_OBJ[SESSION_ID];
|
|
1264
|
+
const candidates = func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource);
|
|
1265
|
+
let last_error = null;
|
|
1266
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
1267
|
+
const candidate = candidates[index];
|
|
1268
|
+
try {
|
|
1269
|
+
return await func.utils.get_plugin_resource(SESSION_ID, plugin_name, candidate);
|
|
1270
|
+
} catch (error) {
|
|
1271
|
+
last_error = error;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
throw last_error || new Error(`plugin resource not found: ${plugin_name}/${resource}`);
|
|
1076
1275
|
};
|
|
1077
1276
|
func.runtime.resources.load_plugin_runtime_css = async function (SESSION_ID, plugin_name, plugin) {
|
|
1078
1277
|
if (!plugin?.manifest?.['runtime.mjs']?.dist || !plugin?.manifest?.['runtime.mjs']?.css) {
|
|
@@ -1102,12 +1301,10 @@ func.runtime.resources.run_ui_plugin = async function (SESSION_ID, paramsP, $elm
|
|
|
1102
1301
|
|
|
1103
1302
|
await func.runtime.resources.load_plugin_runtime_css(SESSION_ID, plugin_name, plugin);
|
|
1104
1303
|
|
|
1105
|
-
const
|
|
1106
|
-
const plugin_index_resources = await import(plugin_index_src);
|
|
1304
|
+
const plugin_index_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'index.mjs');
|
|
1107
1305
|
const properties = await func.runtime.resources.resolve_plugin_properties(SESSION_ID, paramsP.dsSessionP, value?.attributes, plugin_index_resources.properties);
|
|
1108
1306
|
|
|
1109
|
-
const
|
|
1110
|
-
const plugin_runtime_resources = await import(plugin_runtime_src);
|
|
1307
|
+
const plugin_runtime_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'runtime.mjs');
|
|
1111
1308
|
|
|
1112
1309
|
if (plugin_runtime_resources.cdn && Array.isArray(plugin_runtime_resources.cdn)) {
|
|
1113
1310
|
for await (const resource of plugin_runtime_resources.cdn) {
|
|
@@ -1190,25 +1387,52 @@ func.runtime.widgets.get_fields_data = async function (context, fields, props) {
|
|
|
1190
1387
|
|
|
1191
1388
|
return { code: return_code, data: data_obj };
|
|
1192
1389
|
};
|
|
1390
|
+
func.runtime.widgets.get_resource_candidates = function (context, resource) {
|
|
1391
|
+
return func.runtime.resources.get_plugin_resource_candidates(context._session, context.plugin, resource);
|
|
1392
|
+
};
|
|
1393
|
+
func.runtime.widgets.normalize_capabilities = function (definition) {
|
|
1394
|
+
const capabilities = definition?.capabilities || {};
|
|
1395
|
+
return {
|
|
1396
|
+
browser: capabilities.browser !== false,
|
|
1397
|
+
headless: capabilities.headless === true,
|
|
1398
|
+
};
|
|
1399
|
+
};
|
|
1400
|
+
func.runtime.widgets.supports_current_environment = function (definition) {
|
|
1401
|
+
const capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
1402
|
+
if (func.runtime.platform.has_document()) {
|
|
1403
|
+
return capabilities.browser !== false;
|
|
1404
|
+
}
|
|
1405
|
+
return !!capabilities.headless;
|
|
1406
|
+
};
|
|
1193
1407
|
func.runtime.widgets.get_resource_path = function (context, resource) {
|
|
1408
|
+
const relative_path = func.runtime.widgets.get_resource_candidates(context, resource)[0] || resource;
|
|
1194
1409
|
if (context._session.worker_type === 'Dev') {
|
|
1195
|
-
return `../../plugins/${context.plugin_name}/${
|
|
1410
|
+
return `../../plugins/${context.plugin_name}/${relative_path}`;
|
|
1196
1411
|
}
|
|
1197
|
-
|
|
1198
|
-
const dist_prefix = manifest_entry?.dist ? 'dist/' : '';
|
|
1199
|
-
return `https://${context._session.domain}/plugins/${context.plugin_name}/${dist_prefix}${resource}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
|
|
1412
|
+
return `https://${context._session.domain}/plugins/${context.plugin_name}/${relative_path}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
|
|
1200
1413
|
};
|
|
1201
1414
|
func.runtime.widgets.load_css_style = function (context) {
|
|
1202
1415
|
func.utils.load_css_on_demand(func.runtime.widgets.get_resource_path(context, 'style.css'));
|
|
1203
1416
|
return true;
|
|
1204
1417
|
};
|
|
1205
1418
|
func.runtime.widgets.get_resource = async function (context, resource) {
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
|
|
1419
|
+
const candidates = func.runtime.widgets.get_resource_candidates(context, resource);
|
|
1420
|
+
let last_error = null;
|
|
1421
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
1422
|
+
const candidate = candidates[index];
|
|
1423
|
+
try {
|
|
1424
|
+
return await func.utils.get_plugin_resource(context.SESSION_ID, context.plugin_name, candidate);
|
|
1425
|
+
} catch (error) {
|
|
1426
|
+
last_error = error;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
throw last_error || new Error(`widget resource not found: ${context.plugin_name}/${resource}`);
|
|
1430
|
+
};
|
|
1431
|
+
func.runtime.widgets.get_definition = async function (context) {
|
|
1432
|
+
return await func.runtime.widgets.get_resource(context, 'index.mjs');
|
|
1209
1433
|
};
|
|
1210
1434
|
func.runtime.widgets.get_methods = async function (context) {
|
|
1211
|
-
const index = await func.runtime.widgets.
|
|
1435
|
+
const index = await func.runtime.widgets.get_definition(context);
|
|
1212
1436
|
return index?.methods || {};
|
|
1213
1437
|
};
|
|
1214
1438
|
func.runtime.widgets.load_runtime_css = async function (context) {
|
|
@@ -1219,7 +1443,7 @@ func.runtime.widgets.load_runtime_css = async function (context) {
|
|
|
1219
1443
|
func.utils.load_css_on_demand(plugin_runtime_css_url);
|
|
1220
1444
|
return true;
|
|
1221
1445
|
};
|
|
1222
|
-
func.runtime.widgets.build_params = function (context,
|
|
1446
|
+
func.runtime.widgets.build_params = function (context, container_node, container_data, plugin_setup, api_utils, extra = {}) {
|
|
1223
1447
|
return {
|
|
1224
1448
|
SESSION_ID: context.SESSION_ID,
|
|
1225
1449
|
method: context.method,
|
|
@@ -1228,14 +1452,28 @@ func.runtime.widgets.build_params = function (context, $containerP, plugin_setup
|
|
|
1228
1452
|
sourceP: context.sourceP,
|
|
1229
1453
|
propsP: context.propsP,
|
|
1230
1454
|
plugin_name: context.plugin_name,
|
|
1231
|
-
|
|
1455
|
+
container_node,
|
|
1456
|
+
container_data,
|
|
1232
1457
|
plugin_setup,
|
|
1233
1458
|
report_error: function (descP, warn) {
|
|
1234
1459
|
return func.runtime.widgets.report_error(context, descP, warn);
|
|
1235
1460
|
},
|
|
1461
|
+
log_error: function (descP, warn) {
|
|
1462
|
+
return func.runtime.widgets.report_error(context, descP, warn);
|
|
1463
|
+
},
|
|
1236
1464
|
call_plugin_api: async function (plugin_nameP, dataP) {
|
|
1237
1465
|
return await func.utils.call_plugin_api(context.SESSION_ID, plugin_nameP, dataP);
|
|
1238
1466
|
},
|
|
1467
|
+
set_SYS_GLOBAL_OBJ_WIDGET_INFO: async function (docP) {
|
|
1468
|
+
return await func.utils.set_SYS_GLOBAL_OBJ_WIDGET_INFO(context.SESSION_ID, docP);
|
|
1469
|
+
},
|
|
1470
|
+
run_widgetCallbackEvent: async function () {
|
|
1471
|
+
const event_id = context.propsP?.widgetCallbackEvent;
|
|
1472
|
+
if (!event_id || !api_utils?.invoke_event) {
|
|
1473
|
+
return false;
|
|
1474
|
+
}
|
|
1475
|
+
return await api_utils.invoke_event(event_id);
|
|
1476
|
+
},
|
|
1239
1477
|
api_utils,
|
|
1240
1478
|
...extra,
|
|
1241
1479
|
};
|
|
@@ -2325,6 +2563,691 @@ func.common.fastHash = function (inputString) {
|
|
|
2325
2563
|
};
|
|
2326
2564
|
|
|
2327
2565
|
glb.new_xu_render = false;
|
|
2566
|
+
func.runtime = func.runtime || {};
|
|
2567
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
2568
|
+
func.runtime.render = func.runtime.render || {};
|
|
2569
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
2570
|
+
|
|
2571
|
+
// Shared render-tree contract helpers live here so browser and headless runtimes can resolve the same UI structure.
|
|
2572
|
+
|
|
2573
|
+
func.runtime.render.TREE_CONTRACT_VERSION = func.runtime.render.TREE_CONTRACT_VERSION || 'xuda.render_tree.v1';
|
|
2574
|
+
func.runtime.render._tree_widget_capability_cache = func.runtime.render._tree_widget_capability_cache || {};
|
|
2575
|
+
|
|
2576
|
+
func.runtime.render.safe_clone_tree_value = function (value) {
|
|
2577
|
+
if (typeof structuredClone === 'function') {
|
|
2578
|
+
try {
|
|
2579
|
+
return structuredClone(value);
|
|
2580
|
+
} catch (_) {
|
|
2581
|
+
// Fall through to the recursive clone below.
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
if (Array.isArray(value)) {
|
|
2586
|
+
return value.map(function (item) {
|
|
2587
|
+
return func.runtime.render.safe_clone_tree_value(item);
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
if (value && typeof value === 'object') {
|
|
2592
|
+
const cloned = {};
|
|
2593
|
+
const keys = Object.keys(value);
|
|
2594
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2595
|
+
const key = keys[index];
|
|
2596
|
+
cloned[key] = func.runtime.render.safe_clone_tree_value(value[key]);
|
|
2597
|
+
}
|
|
2598
|
+
return cloned;
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
return value;
|
|
2602
|
+
};
|
|
2603
|
+
func.runtime.render.sort_tree_debug_value = function (value) {
|
|
2604
|
+
if (Array.isArray(value)) {
|
|
2605
|
+
return value.map(function (item) {
|
|
2606
|
+
return func.runtime.render.sort_tree_debug_value(item);
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
if (value && typeof value === 'object') {
|
|
2611
|
+
const sorted = {};
|
|
2612
|
+
const keys = Object.keys(value).sort();
|
|
2613
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2614
|
+
const key = keys[index];
|
|
2615
|
+
sorted[key] = func.runtime.render.sort_tree_debug_value(value[key]);
|
|
2616
|
+
}
|
|
2617
|
+
return sorted;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
return value;
|
|
2621
|
+
};
|
|
2622
|
+
func.runtime.render.is_tree_node = function (nodeP) {
|
|
2623
|
+
return !!nodeP?.contract && nodeP.contract === func.runtime.render.TREE_CONTRACT_VERSION;
|
|
2624
|
+
};
|
|
2625
|
+
func.runtime.render.get_tree_source_node = function (nodeP) {
|
|
2626
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
2627
|
+
return nodeP || null;
|
|
2628
|
+
}
|
|
2629
|
+
return nodeP?.meta?.source_node || null;
|
|
2630
|
+
};
|
|
2631
|
+
func.runtime.render.get_tree_source_snapshot = function (nodeP) {
|
|
2632
|
+
if (!func.runtime.render.is_tree_node(nodeP)) {
|
|
2633
|
+
return func.runtime.render.safe_clone_tree_value(nodeP);
|
|
2634
|
+
}
|
|
2635
|
+
return nodeP?.meta?.source_snapshot || null;
|
|
2636
|
+
};
|
|
2637
|
+
func.runtime.render.get_tree_node_kind = function (nodeP) {
|
|
2638
|
+
const tag_name = typeof nodeP?.tagName === 'string' ? nodeP.tagName.toLowerCase() : '';
|
|
2639
|
+
const node_type = typeof nodeP?.type === 'string' ? nodeP.type.toLowerCase() : '';
|
|
2640
|
+
|
|
2641
|
+
if (tag_name === 'xu-widget') return 'widget';
|
|
2642
|
+
if (tag_name === 'xu-single-view') return 'single_view';
|
|
2643
|
+
if (tag_name === 'xu-multi-view') return 'multi_view';
|
|
2644
|
+
if (tag_name === 'xu-panel') return 'panel';
|
|
2645
|
+
if (tag_name === 'xu-teleport') return 'teleport';
|
|
2646
|
+
if (tag_name === 'xurender') return 'placeholder';
|
|
2647
|
+
if (tag_name === '#text' || node_type === 'text') return 'text';
|
|
2648
|
+
if (!tag_name && typeof nodeP?.content === 'string' && !Array.isArray(nodeP?.children)) return 'text';
|
|
2649
|
+
return 'element';
|
|
2650
|
+
};
|
|
2651
|
+
func.runtime.render.get_tree_node_id = function (nodeP, pathP) {
|
|
2652
|
+
if (nodeP?.id) {
|
|
2653
|
+
return nodeP.id;
|
|
2654
|
+
}
|
|
2655
|
+
if (nodeP?.id_org) {
|
|
2656
|
+
return nodeP.id_org;
|
|
2657
|
+
}
|
|
2658
|
+
const normalized_path = Array.isArray(pathP) && pathP.length ? pathP.join('.') : 'root';
|
|
2659
|
+
return `tree-node-${normalized_path}`;
|
|
2660
|
+
};
|
|
2661
|
+
func.runtime.render.get_tree_controls = function (attributes) {
|
|
2662
|
+
const attrs = attributes || {};
|
|
2663
|
+
const get_first_defined = function (keys) {
|
|
2664
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2665
|
+
const key = keys[index];
|
|
2666
|
+
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
|
|
2667
|
+
return attrs[key];
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
return null;
|
|
2671
|
+
};
|
|
2672
|
+
return {
|
|
2673
|
+
xu_for: get_first_defined(['xu-for', 'xu-exp:xu-for']),
|
|
2674
|
+
xu_if: get_first_defined(['xu-if', 'xu-exp:xu-if']),
|
|
2675
|
+
xu_render: get_first_defined(['xu-render', 'xu-exp:xu-render']),
|
|
2676
|
+
};
|
|
2677
|
+
};
|
|
2678
|
+
func.runtime.render.get_tree_node_capabilities = async function (options) {
|
|
2679
|
+
const attributes = options?.attributes || {};
|
|
2680
|
+
const plugin_name = attributes['xu-widget'];
|
|
2681
|
+
if (!plugin_name) {
|
|
2682
|
+
return null;
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
const cache = func.runtime.render._tree_widget_capability_cache;
|
|
2686
|
+
if (cache[plugin_name]) {
|
|
2687
|
+
return func.runtime.render.safe_clone_tree_value(cache[plugin_name]);
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
let capabilities = {
|
|
2691
|
+
browser: true,
|
|
2692
|
+
headless: false,
|
|
2693
|
+
};
|
|
2694
|
+
|
|
2695
|
+
try {
|
|
2696
|
+
if (options.SESSION_ID && options.paramsP && func.runtime.widgets?.create_context && func.runtime.widgets?.get_definition) {
|
|
2697
|
+
const widget_context = func.runtime.widgets.create_context(options.SESSION_ID, options.paramsP, attributes);
|
|
2698
|
+
const definition = await func.runtime.widgets.get_definition(widget_context);
|
|
2699
|
+
capabilities = func.runtime.widgets.normalize_capabilities(definition);
|
|
2700
|
+
}
|
|
2701
|
+
} catch (_) {
|
|
2702
|
+
// Keep the safe browser-only default when the widget definition is unavailable.
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
cache[plugin_name] = capabilities;
|
|
2706
|
+
return func.runtime.render.safe_clone_tree_value(capabilities);
|
|
2707
|
+
};
|
|
2708
|
+
func.runtime.render.ensure_tree_node = async function (options) {
|
|
2709
|
+
if (!options?.nodeP) {
|
|
2710
|
+
return null;
|
|
2711
|
+
}
|
|
2712
|
+
if (func.runtime.render.is_tree_node(options.nodeP)) {
|
|
2713
|
+
return options.nodeP;
|
|
2714
|
+
}
|
|
2715
|
+
return await func.runtime.render.build_tree(options);
|
|
2716
|
+
};
|
|
2717
|
+
func.runtime.render.build_tree = async function (options) {
|
|
2718
|
+
if (Array.isArray(options?.nodeP)) {
|
|
2719
|
+
return await func.runtime.render.build_tree_list({
|
|
2720
|
+
...options,
|
|
2721
|
+
nodesP: options.nodeP,
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
const nodeP = options?.nodeP;
|
|
2726
|
+
if (!nodeP) {
|
|
2727
|
+
return null;
|
|
2728
|
+
}
|
|
2729
|
+
if (func.runtime.render.is_tree_node(nodeP)) {
|
|
2730
|
+
return nodeP;
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
const pathP = Array.isArray(options?.pathP) ? options.pathP.slice() : [];
|
|
2734
|
+
const tree_path = pathP.length ? pathP.slice() : [0];
|
|
2735
|
+
const attributes = func.runtime.render.safe_clone_tree_value(nodeP.attributes || {});
|
|
2736
|
+
if (typeof nodeP.content !== 'undefined' && typeof attributes['xu-content'] === 'undefined') {
|
|
2737
|
+
attributes['xu-content'] = func.runtime.render.safe_clone_tree_value(nodeP.content);
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
const widget_capabilities = await func.runtime.render.get_tree_node_capabilities({
|
|
2741
|
+
SESSION_ID: options?.SESSION_ID,
|
|
2742
|
+
paramsP: options?.paramsP,
|
|
2743
|
+
attributes,
|
|
2744
|
+
});
|
|
2745
|
+
const children = [];
|
|
2746
|
+
const child_nodes = Array.isArray(nodeP.children) ? nodeP.children : [];
|
|
2747
|
+
const parent_tree_id = tree_path.join('.');
|
|
2748
|
+
|
|
2749
|
+
for (let index = 0; index < child_nodes.length; index++) {
|
|
2750
|
+
const child_tree = await func.runtime.render.build_tree({
|
|
2751
|
+
...options,
|
|
2752
|
+
nodeP: child_nodes[index],
|
|
2753
|
+
pathP: tree_path.concat(index),
|
|
2754
|
+
parent_tree_id: parent_tree_id,
|
|
2755
|
+
keyP: index,
|
|
2756
|
+
parent_nodeP: nodeP,
|
|
2757
|
+
});
|
|
2758
|
+
if (child_tree) {
|
|
2759
|
+
children.push(child_tree);
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
const tree = {
|
|
2764
|
+
contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
2765
|
+
id: func.runtime.render.get_tree_node_id(nodeP, tree_path),
|
|
2766
|
+
xu_tree_id: `tree.${tree_path.join('.')}`,
|
|
2767
|
+
kind: func.runtime.render.get_tree_node_kind(nodeP),
|
|
2768
|
+
tagName: nodeP.tagName || null,
|
|
2769
|
+
attributes,
|
|
2770
|
+
text: typeof nodeP.text !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.text) : null,
|
|
2771
|
+
content: typeof nodeP.content !== 'undefined' ? func.runtime.render.safe_clone_tree_value(nodeP.content) : null,
|
|
2772
|
+
children,
|
|
2773
|
+
meta: {
|
|
2774
|
+
tree_id: tree_path.join('.'),
|
|
2775
|
+
path: tree_path,
|
|
2776
|
+
parent_tree_id: options?.parent_tree_id || null,
|
|
2777
|
+
key: typeof options?.keyP === 'undefined' ? null : options.keyP,
|
|
2778
|
+
recordid: nodeP?.recordid || null,
|
|
2779
|
+
dependency_fields: func.runtime.render.safe_clone_tree_value(nodeP?.dependency_fields || null),
|
|
2780
|
+
iterate_info: func.runtime.render.safe_clone_tree_value(options?.parent_infoP?.iterate_info || nodeP?.iterate_info || null),
|
|
2781
|
+
controls: func.runtime.render.get_tree_controls(attributes),
|
|
2782
|
+
capabilities: widget_capabilities,
|
|
2783
|
+
widget: attributes['xu-widget']
|
|
2784
|
+
? {
|
|
2785
|
+
plugin_name: attributes['xu-widget'],
|
|
2786
|
+
method: attributes['xu-method'] || '_default',
|
|
2787
|
+
capabilities: widget_capabilities,
|
|
2788
|
+
}
|
|
2789
|
+
: null,
|
|
2790
|
+
source_node_id: nodeP?.id || nodeP?.id_org || null,
|
|
2791
|
+
source_node: nodeP,
|
|
2792
|
+
source_snapshot: func.runtime.ui?.get_node_snapshot
|
|
2793
|
+
? func.runtime.ui.get_node_snapshot(nodeP)
|
|
2794
|
+
: func.runtime.render.safe_clone_tree_value(nodeP),
|
|
2795
|
+
},
|
|
2796
|
+
};
|
|
2797
|
+
|
|
2798
|
+
return tree;
|
|
2799
|
+
};
|
|
2800
|
+
func.runtime.render.build_tree_list = async function (options) {
|
|
2801
|
+
const nodes = Array.isArray(options?.nodesP) ? options.nodesP : [];
|
|
2802
|
+
const trees = [];
|
|
2803
|
+
|
|
2804
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
2805
|
+
const tree = await func.runtime.render.build_tree({
|
|
2806
|
+
...options,
|
|
2807
|
+
nodeP: nodes[index],
|
|
2808
|
+
pathP: Array.isArray(options?.pathP) && options.pathP.length ? options.pathP.concat(index) : [index],
|
|
2809
|
+
keyP: index,
|
|
2810
|
+
});
|
|
2811
|
+
if (tree) {
|
|
2812
|
+
trees.push(tree);
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
return trees;
|
|
2817
|
+
};
|
|
2818
|
+
func.runtime.render.sanitize_tree_for_debug = function (treeP) {
|
|
2819
|
+
if (Array.isArray(treeP)) {
|
|
2820
|
+
return treeP.map(function (child) {
|
|
2821
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
2822
|
+
});
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
if (!func.runtime.render.is_tree_node(treeP)) {
|
|
2826
|
+
return func.runtime.render.sort_tree_debug_value(func.runtime.render.safe_clone_tree_value(treeP));
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
return {
|
|
2830
|
+
contract: treeP.contract,
|
|
2831
|
+
id: treeP.id,
|
|
2832
|
+
xu_tree_id: treeP.xu_tree_id || null,
|
|
2833
|
+
kind: treeP.kind,
|
|
2834
|
+
tagName: treeP.tagName,
|
|
2835
|
+
attributes: func.runtime.render.sort_tree_debug_value(treeP.attributes || {}),
|
|
2836
|
+
text: treeP.text,
|
|
2837
|
+
content: treeP.content,
|
|
2838
|
+
children: treeP.children.map(function (child) {
|
|
2839
|
+
return func.runtime.render.sanitize_tree_for_debug(child);
|
|
2840
|
+
}),
|
|
2841
|
+
meta: {
|
|
2842
|
+
tree_id: treeP.meta?.tree_id || null,
|
|
2843
|
+
path: func.runtime.render.safe_clone_tree_value(treeP.meta?.path || []),
|
|
2844
|
+
parent_tree_id: treeP.meta?.parent_tree_id || null,
|
|
2845
|
+
key: typeof treeP.meta?.key === 'undefined' ? null : treeP.meta.key,
|
|
2846
|
+
recordid: treeP.meta?.recordid || null,
|
|
2847
|
+
dependency_fields: func.runtime.render.sort_tree_debug_value(treeP.meta?.dependency_fields || null),
|
|
2848
|
+
iterate_info: func.runtime.render.sort_tree_debug_value(treeP.meta?.iterate_info || null),
|
|
2849
|
+
controls: func.runtime.render.sort_tree_debug_value(treeP.meta?.controls || null),
|
|
2850
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta?.capabilities || null),
|
|
2851
|
+
widget: treeP.meta?.widget
|
|
2852
|
+
? {
|
|
2853
|
+
plugin_name: treeP.meta.widget.plugin_name,
|
|
2854
|
+
method: treeP.meta.widget.method,
|
|
2855
|
+
capabilities: func.runtime.render.sort_tree_debug_value(treeP.meta.widget.capabilities || null),
|
|
2856
|
+
}
|
|
2857
|
+
: null,
|
|
2858
|
+
source_node_id: treeP.meta?.source_node_id || null,
|
|
2859
|
+
},
|
|
2860
|
+
};
|
|
2861
|
+
};
|
|
2862
|
+
func.runtime.render.serialize_tree = function (treeP, spacing = 2) {
|
|
2863
|
+
return JSON.stringify(func.runtime.render.sanitize_tree_for_debug(treeP), null, spacing);
|
|
2864
|
+
};
|
|
2865
|
+
func.runtime = func.runtime || {};
|
|
2866
|
+
func.runtime.ui = func.runtime.ui || {};
|
|
2867
|
+
func.runtime.render = func.runtime.render || {};
|
|
2868
|
+
func.runtime.widgets = func.runtime.widgets || {};
|
|
2869
|
+
|
|
2870
|
+
// Shared string-renderer helpers live here so headless/server runtimes can materialize the render tree without a DOM.
|
|
2871
|
+
|
|
2872
|
+
func.runtime.render.HTML_VOID_TAGS = func.runtime.render.HTML_VOID_TAGS || {
|
|
2873
|
+
area: true,
|
|
2874
|
+
base: true,
|
|
2875
|
+
br: true,
|
|
2876
|
+
col: true,
|
|
2877
|
+
embed: true,
|
|
2878
|
+
hr: true,
|
|
2879
|
+
img: true,
|
|
2880
|
+
input: true,
|
|
2881
|
+
link: true,
|
|
2882
|
+
meta: true,
|
|
2883
|
+
param: true,
|
|
2884
|
+
source: true,
|
|
2885
|
+
track: true,
|
|
2886
|
+
wbr: true,
|
|
2887
|
+
};
|
|
2888
|
+
func.runtime.render.escape_html = function (value) {
|
|
2889
|
+
return `${value ?? ''}`
|
|
2890
|
+
.replaceAll('&', '&')
|
|
2891
|
+
.replaceAll('<', '<')
|
|
2892
|
+
.replaceAll('>', '>')
|
|
2893
|
+
.replaceAll('"', '"')
|
|
2894
|
+
.replaceAll("'", ''');
|
|
2895
|
+
};
|
|
2896
|
+
func.runtime.render.escape_html_attribute = function (value) {
|
|
2897
|
+
return func.runtime.render.escape_html(value);
|
|
2898
|
+
};
|
|
2899
|
+
func.runtime.render.is_html_void_tag = function (tag_name) {
|
|
2900
|
+
return !!func.runtime.render.HTML_VOID_TAGS[(tag_name || '').toLowerCase()];
|
|
2901
|
+
};
|
|
2902
|
+
func.runtime.render.is_falsey_render_value = function (value) {
|
|
2903
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
2904
|
+
return true;
|
|
2905
|
+
}
|
|
2906
|
+
if (typeof value === 'number') {
|
|
2907
|
+
return value === 0;
|
|
2908
|
+
}
|
|
2909
|
+
if (typeof value === 'string') {
|
|
2910
|
+
const normalized = value.trim().toLowerCase();
|
|
2911
|
+
return normalized === '' || normalized === 'false' || normalized === '0' || normalized === 'null' || normalized === 'undefined' || normalized === 'off' || normalized === 'no';
|
|
2912
|
+
}
|
|
2913
|
+
return false;
|
|
2914
|
+
};
|
|
2915
|
+
func.runtime.render.should_render_tree_node = function (treeP) {
|
|
2916
|
+
const controls = treeP?.meta?.controls || {};
|
|
2917
|
+
if (controls.xu_if !== null && controls.xu_if !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_if)) {
|
|
2918
|
+
return false;
|
|
2919
|
+
}
|
|
2920
|
+
if (controls.xu_render !== null && controls.xu_render !== undefined && func.runtime.render.is_falsey_render_value(controls.xu_render)) {
|
|
2921
|
+
return false;
|
|
2922
|
+
}
|
|
2923
|
+
return true;
|
|
2924
|
+
};
|
|
2925
|
+
func.runtime.render.is_tree_control_attribute = function (key) {
|
|
2926
|
+
if (!key) {
|
|
2927
|
+
return false;
|
|
2928
|
+
}
|
|
2929
|
+
return (
|
|
2930
|
+
key.startsWith('xu-exp:') ||
|
|
2931
|
+
key === 'xu-widget' ||
|
|
2932
|
+
key === 'xu-method' ||
|
|
2933
|
+
key === 'xu-for' ||
|
|
2934
|
+
key === 'xu-for-key' ||
|
|
2935
|
+
key === 'xu-for-val' ||
|
|
2936
|
+
key === 'xu-if' ||
|
|
2937
|
+
key === 'xu-render' ||
|
|
2938
|
+
key === 'xu-bind' ||
|
|
2939
|
+
key === 'xu-content' ||
|
|
2940
|
+
key === 'xu-text' ||
|
|
2941
|
+
key === 'xu-html' ||
|
|
2942
|
+
key === 'xu-show' ||
|
|
2943
|
+
key === 'xu-panel-program' ||
|
|
2944
|
+
key === 'xu-teleport'
|
|
2945
|
+
);
|
|
2946
|
+
};
|
|
2947
|
+
func.runtime.render.get_string_renderer_tag_name = function (treeP) {
|
|
2948
|
+
switch (treeP?.kind) {
|
|
2949
|
+
case 'widget':
|
|
2950
|
+
case 'single_view':
|
|
2951
|
+
case 'multi_view':
|
|
2952
|
+
case 'panel':
|
|
2953
|
+
case 'teleport':
|
|
2954
|
+
return 'div';
|
|
2955
|
+
case 'placeholder':
|
|
2956
|
+
return null;
|
|
2957
|
+
case 'text':
|
|
2958
|
+
return null;
|
|
2959
|
+
default:
|
|
2960
|
+
return treeP?.tagName || 'div';
|
|
2961
|
+
}
|
|
2962
|
+
};
|
|
2963
|
+
func.runtime.render.get_tree_terminal_content = function (treeP) {
|
|
2964
|
+
const attributes = treeP?.attributes || {};
|
|
2965
|
+
if (typeof attributes['xu-html'] !== 'undefined' && attributes['xu-html'] !== null) {
|
|
2966
|
+
return {
|
|
2967
|
+
value: `${attributes['xu-html']}`,
|
|
2968
|
+
mode: 'html',
|
|
2969
|
+
};
|
|
2970
|
+
}
|
|
2971
|
+
if (typeof attributes['xu-content'] !== 'undefined' && attributes['xu-content'] !== null) {
|
|
2972
|
+
return {
|
|
2973
|
+
value: `${attributes['xu-content']}`,
|
|
2974
|
+
mode: 'html',
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
if (typeof attributes['xu-text'] !== 'undefined' && attributes['xu-text'] !== null) {
|
|
2978
|
+
return {
|
|
2979
|
+
value: `${attributes['xu-text']}`,
|
|
2980
|
+
mode: 'text',
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
if (treeP?.kind === 'text') {
|
|
2984
|
+
return {
|
|
2985
|
+
value: typeof treeP?.text !== 'undefined' && treeP?.text !== null ? `${treeP.text}` : `${treeP?.content || ''}`,
|
|
2986
|
+
mode: 'text',
|
|
2987
|
+
};
|
|
2988
|
+
}
|
|
2989
|
+
return null;
|
|
2990
|
+
};
|
|
2991
|
+
func.runtime.render.render_tree_terminal_content = function (treeP) {
|
|
2992
|
+
const terminal = func.runtime.render.get_tree_terminal_content(treeP);
|
|
2993
|
+
if (!terminal) {
|
|
2994
|
+
return null;
|
|
2995
|
+
}
|
|
2996
|
+
if (terminal.mode === 'html') {
|
|
2997
|
+
return terminal.value;
|
|
2998
|
+
}
|
|
2999
|
+
return func.runtime.render.escape_html(terminal.value);
|
|
3000
|
+
};
|
|
3001
|
+
func.runtime.render.get_widget_fallback_markup = function (treeP) {
|
|
3002
|
+
const widget_meta = treeP?.meta?.widget || {};
|
|
3003
|
+
const capability_state = widget_meta?.capabilities?.headless ? 'headless-capable' : 'browser-only';
|
|
3004
|
+
return `<!--xuda-widget:${func.runtime.render.escape_html(widget_meta.plugin_name || 'unknown')}:${capability_state}-->`;
|
|
3005
|
+
};
|
|
3006
|
+
func.runtime.render.get_tree_string_attributes = function (treeP, renderer_context) {
|
|
3007
|
+
const attributes = func.runtime.render.safe_clone_tree_value(treeP?.attributes || {});
|
|
3008
|
+
const attr_pairs = [];
|
|
3009
|
+
const keys = Object.keys(attributes);
|
|
3010
|
+
|
|
3011
|
+
for (let index = 0; index < keys.length; index++) {
|
|
3012
|
+
const key = keys[index];
|
|
3013
|
+
if (func.runtime.render.is_tree_control_attribute(key)) {
|
|
3014
|
+
continue;
|
|
3015
|
+
}
|
|
3016
|
+
const value = attributes[key];
|
|
3017
|
+
if (value === false || value === null || typeof value === 'undefined') {
|
|
3018
|
+
continue;
|
|
3019
|
+
}
|
|
3020
|
+
if (value === true) {
|
|
3021
|
+
attr_pairs.push(key);
|
|
3022
|
+
continue;
|
|
3023
|
+
}
|
|
3024
|
+
const normalized_value = typeof value === 'object' ? JSON.stringify(value) : `${value}`;
|
|
3025
|
+
attr_pairs.push(`${key}="${func.runtime.render.escape_html_attribute(normalized_value)}"`);
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
attr_pairs.push(`data-xuda-kind="${func.runtime.render.escape_html_attribute(treeP?.kind || 'element')}"`);
|
|
3029
|
+
attr_pairs.push(`data-xuda-node-id="${func.runtime.render.escape_html_attribute(treeP?.id || treeP?.meta?.source_node_id || '')}"`);
|
|
3030
|
+
attr_pairs.push(`data-xuda-tree-id="${func.runtime.render.escape_html_attribute(treeP?.meta?.tree_id || '')}"`);
|
|
3031
|
+
|
|
3032
|
+
if (treeP?.kind === 'widget' && treeP?.meta?.widget) {
|
|
3033
|
+
attr_pairs.push(`data-xuda-widget="${func.runtime.render.escape_html_attribute(treeP.meta.widget.plugin_name || '')}"`);
|
|
3034
|
+
attr_pairs.push(`data-xuda-widget-method="${func.runtime.render.escape_html_attribute(treeP.meta.widget.method || '_default')}"`);
|
|
3035
|
+
attr_pairs.push(`data-xuda-widget-capability="${func.runtime.render.escape_html_attribute(treeP.meta.widget.capabilities?.headless ? 'headless' : 'browser')}"`);
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
if (treeP?.kind === 'teleport' && treeP?.attributes?.['xu-teleport']) {
|
|
3039
|
+
attr_pairs.push(`data-xuda-teleport-target="${func.runtime.render.escape_html_attribute(treeP.attributes['xu-teleport'])}"`);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
if ((treeP?.meta?.controls?.xu_for !== null && treeP?.meta?.controls?.xu_for !== undefined) && !renderer_context?.strip_iteration_markers) {
|
|
3043
|
+
attr_pairs.push('data-xuda-xu-for="pending"');
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
return attr_pairs.length ? ' ' + attr_pairs.join(' ') : '';
|
|
3047
|
+
};
|
|
3048
|
+
func.runtime.render.render_tree_children_to_string = async function (treeP, renderer_context) {
|
|
3049
|
+
if (!Array.isArray(treeP?.children) || !treeP.children.length) {
|
|
3050
|
+
return '';
|
|
3051
|
+
}
|
|
3052
|
+
let html = '';
|
|
3053
|
+
for (let index = 0; index < treeP.children.length; index++) {
|
|
3054
|
+
html += await func.runtime.render.render_tree_to_string(treeP.children[index], {
|
|
3055
|
+
...renderer_context,
|
|
3056
|
+
parent_tree: treeP,
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
3059
|
+
return html;
|
|
3060
|
+
};
|
|
3061
|
+
func.runtime.render.render_tree_to_string = async function (treeP, renderer_context = {}) {
|
|
3062
|
+
if (!treeP) {
|
|
3063
|
+
return '';
|
|
3064
|
+
}
|
|
3065
|
+
if (Array.isArray(treeP)) {
|
|
3066
|
+
let html = '';
|
|
3067
|
+
for (let index = 0; index < treeP.length; index++) {
|
|
3068
|
+
html += await func.runtime.render.render_tree_to_string(treeP[index], renderer_context);
|
|
3069
|
+
}
|
|
3070
|
+
return html;
|
|
3071
|
+
}
|
|
3072
|
+
|
|
3073
|
+
const ensured_tree = await func.runtime.render.ensure_tree_node({
|
|
3074
|
+
SESSION_ID: renderer_context?.SESSION_ID,
|
|
3075
|
+
nodeP: treeP,
|
|
3076
|
+
paramsP: renderer_context?.paramsP,
|
|
3077
|
+
parent_infoP: renderer_context?.parent_infoP,
|
|
3078
|
+
keyP: renderer_context?.keyP,
|
|
3079
|
+
parent_nodeP: renderer_context?.parent_nodeP,
|
|
3080
|
+
});
|
|
3081
|
+
|
|
3082
|
+
if (!ensured_tree || !func.runtime.render.should_render_tree_node(ensured_tree)) {
|
|
3083
|
+
return '';
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
if (ensured_tree.kind === 'placeholder') {
|
|
3087
|
+
if (renderer_context?.include_placeholders) {
|
|
3088
|
+
return `<!--xuda-placeholder:${func.runtime.render.escape_html(ensured_tree.id || '')}-->`;
|
|
3089
|
+
}
|
|
3090
|
+
return '';
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
if (ensured_tree.kind === 'text') {
|
|
3094
|
+
return func.runtime.render.render_tree_terminal_content(ensured_tree) || '';
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
const tag_name = func.runtime.render.get_string_renderer_tag_name(ensured_tree);
|
|
3098
|
+
if (!tag_name || tag_name.toLowerCase() === 'script') {
|
|
3099
|
+
return '';
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
const attributes = func.runtime.render.get_tree_string_attributes(ensured_tree, renderer_context);
|
|
3103
|
+
const terminal_content = func.runtime.render.render_tree_terminal_content(ensured_tree);
|
|
3104
|
+
let children_html = terminal_content !== null ? terminal_content : await func.runtime.render.render_tree_children_to_string(ensured_tree, renderer_context);
|
|
3105
|
+
|
|
3106
|
+
if (ensured_tree.kind === 'widget' && !children_html) {
|
|
3107
|
+
children_html = func.runtime.render.get_widget_fallback_markup(ensured_tree);
|
|
3108
|
+
}
|
|
3109
|
+
|
|
3110
|
+
if (func.runtime.render.is_html_void_tag(tag_name)) {
|
|
3111
|
+
return `<${tag_name}${attributes}>`;
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
return `<${tag_name}${attributes}>${children_html}</${tag_name}>`;
|
|
3115
|
+
};
|
|
3116
|
+
func.runtime.render.render_to_string = async function (options = {}) {
|
|
3117
|
+
const treeP = await func.runtime.render.ensure_tree_node({
|
|
3118
|
+
SESSION_ID: options.SESSION_ID,
|
|
3119
|
+
nodeP: options.treeP || options.nodeP,
|
|
3120
|
+
paramsP: options.paramsP,
|
|
3121
|
+
parent_infoP: options.parent_infoP,
|
|
3122
|
+
keyP: options.keyP,
|
|
3123
|
+
parent_nodeP: options.parent_nodeP,
|
|
3124
|
+
});
|
|
3125
|
+
|
|
3126
|
+
return await func.runtime.render.render_tree_to_string(treeP, options);
|
|
3127
|
+
};
|
|
3128
|
+
func.runtime.render.get_server_render_mode = function (options = {}) {
|
|
3129
|
+
const normalized = func.runtime.render.normalize_runtime_bootstrap({
|
|
3130
|
+
app_computing_mode: options.app_computing_mode,
|
|
3131
|
+
app_render_mode: options.app_render_mode,
|
|
3132
|
+
app_client_activation: options.app_client_activation,
|
|
3133
|
+
});
|
|
3134
|
+
|
|
3135
|
+
return normalized;
|
|
3136
|
+
};
|
|
3137
|
+
func.runtime.render.build_server_render_params = async function (options = {}) {
|
|
3138
|
+
const SESSION_ID = options.SESSION_ID;
|
|
3139
|
+
const prog_id = options.prog_id;
|
|
3140
|
+
const dsSessionP = options.dsSessionP;
|
|
3141
|
+
const _session = SESSION_OBJ?.[SESSION_ID] || {};
|
|
3142
|
+
const _ds = _session?.DS_GLB?.[dsSessionP] || {};
|
|
3143
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
3144
|
+
|
|
3145
|
+
if (!viewDoc?.properties) {
|
|
3146
|
+
throw new Error(`view document not found for ${prog_id}`);
|
|
3147
|
+
}
|
|
3148
|
+
|
|
3149
|
+
const base_params = _ds?.screen_params ? func.runtime.render.safe_clone_tree_value(_ds.screen_params) : {};
|
|
3150
|
+
const screenId = options.screenId || base_params.screenId || `ssr_${prog_id}_${dsSessionP || '0'}`;
|
|
3151
|
+
const paramsP = {
|
|
3152
|
+
...base_params,
|
|
3153
|
+
prog_id,
|
|
3154
|
+
sourceScreenP: null,
|
|
3155
|
+
$callingContainerP: null,
|
|
3156
|
+
triggerIdP: null,
|
|
3157
|
+
callingDataSource_objP: _ds,
|
|
3158
|
+
rowIdP: typeof options.rowIdP !== 'undefined' ? options.rowIdP : (_ds?.currentRecordId || null),
|
|
3159
|
+
renderType: viewDoc.properties?.renderType,
|
|
3160
|
+
parameters_obj_inP: options.parameters_obj_inP || base_params.parameters_obj_inP || options.parameters_raw_obj || {},
|
|
3161
|
+
source_functionP: options.source_functionP || base_params.source_functionP || 'render_string',
|
|
3162
|
+
is_panelP: false,
|
|
3163
|
+
screen_type: options.screen_type || base_params.screen_type || 'render_string',
|
|
3164
|
+
screenInfo: viewDoc,
|
|
3165
|
+
call_screen_propertiesP: base_params.call_screen_propertiesP,
|
|
3166
|
+
parentDataSourceNoP: typeof _ds?.parentDataSourceNo === 'undefined' || _ds?.parentDataSourceNo === null ? 0 : _ds.parentDataSourceNo,
|
|
3167
|
+
parameters_raw_obj: options.parameters_raw_obj || base_params.parameters_raw_obj || {},
|
|
3168
|
+
dsSessionP,
|
|
3169
|
+
screenId,
|
|
3170
|
+
containerIdP: base_params.containerIdP || `ssr_container_${screenId}`,
|
|
3171
|
+
};
|
|
3172
|
+
|
|
3173
|
+
if (_ds) {
|
|
3174
|
+
_ds.screen_params = paramsP;
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3177
|
+
return paramsP;
|
|
3178
|
+
};
|
|
3179
|
+
func.runtime.render.build_prog_tree = async function (options = {}) {
|
|
3180
|
+
const SESSION_ID = options.SESSION_ID;
|
|
3181
|
+
const prog_id = options.prog_id;
|
|
3182
|
+
const viewDoc = options.viewDoc || (await func.utils?.VIEWS_OBJ?.get?.(SESSION_ID, prog_id));
|
|
3183
|
+
|
|
3184
|
+
if (!viewDoc?.progUi?.length) {
|
|
3185
|
+
throw new Error(`progUi not found for ${prog_id}`);
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3188
|
+
const paramsP = options.paramsP || (await func.runtime.render.build_server_render_params({
|
|
3189
|
+
...options,
|
|
3190
|
+
SESSION_ID,
|
|
3191
|
+
prog_id,
|
|
3192
|
+
viewDoc,
|
|
3193
|
+
}));
|
|
3194
|
+
const root_index = typeof options.root_index === 'number' ? options.root_index : 0;
|
|
3195
|
+
const root_node = func.runtime.render.safe_clone_tree_value(viewDoc.progUi[root_index]);
|
|
3196
|
+
const tree = await func.runtime.render.build_tree({
|
|
3197
|
+
SESSION_ID,
|
|
3198
|
+
nodeP: root_node,
|
|
3199
|
+
paramsP,
|
|
3200
|
+
});
|
|
3201
|
+
|
|
3202
|
+
return {
|
|
3203
|
+
tree,
|
|
3204
|
+
paramsP,
|
|
3205
|
+
viewDoc,
|
|
3206
|
+
};
|
|
3207
|
+
};
|
|
3208
|
+
func.runtime.render.build_ssr_payload = function (render_program, options = {}) {
|
|
3209
|
+
const runtime_profile = func.runtime.render.get_server_render_mode(options);
|
|
3210
|
+
return {
|
|
3211
|
+
contract: 'xuda.ssr.v1',
|
|
3212
|
+
prog_id: options.prog_id,
|
|
3213
|
+
screenId: render_program.paramsP.screenId,
|
|
3214
|
+
containerId: render_program.paramsP.containerIdP,
|
|
3215
|
+
app_computing_mode: runtime_profile.app_computing_mode,
|
|
3216
|
+
app_render_mode: runtime_profile.app_render_mode,
|
|
3217
|
+
app_client_activation: runtime_profile.app_client_activation,
|
|
3218
|
+
tree_contract: func.runtime.render.TREE_CONTRACT_VERSION,
|
|
3219
|
+
};
|
|
3220
|
+
};
|
|
3221
|
+
func.runtime.render.build_ssr_screen_html = function (html, render_program, options = {}) {
|
|
3222
|
+
const payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
3223
|
+
const screenId = func.runtime.render.escape_html_attribute(payload.screenId || '');
|
|
3224
|
+
const containerId = func.runtime.render.escape_html_attribute(payload.containerId || '');
|
|
3225
|
+
const activation = func.runtime.render.escape_html_attribute(payload.app_client_activation || 'takeover');
|
|
3226
|
+
|
|
3227
|
+
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>`;
|
|
3228
|
+
};
|
|
3229
|
+
func.runtime.render.render_prog_to_string = async function (options = {}) {
|
|
3230
|
+
const render_program = await func.runtime.render.build_prog_tree(options);
|
|
3231
|
+
const html = await func.runtime.render.render_to_string({
|
|
3232
|
+
...options,
|
|
3233
|
+
SESSION_ID: options.SESSION_ID,
|
|
3234
|
+
treeP: render_program.tree,
|
|
3235
|
+
paramsP: render_program.paramsP,
|
|
3236
|
+
});
|
|
3237
|
+
const ssr_payload = func.runtime.render.build_ssr_payload(render_program, options);
|
|
3238
|
+
const screen_html = func.runtime.render.build_ssr_screen_html(html, render_program, options);
|
|
3239
|
+
|
|
3240
|
+
return {
|
|
3241
|
+
prog_id: options.prog_id,
|
|
3242
|
+
dsSessionP: render_program.paramsP.dsSessionP,
|
|
3243
|
+
screenId: render_program.paramsP.screenId,
|
|
3244
|
+
html,
|
|
3245
|
+
screen_html,
|
|
3246
|
+
tree_json: func.runtime.render.serialize_tree(render_program.tree),
|
|
3247
|
+
paramsP: render_program.paramsP,
|
|
3248
|
+
ssr_payload,
|
|
3249
|
+
};
|
|
3250
|
+
};
|
|
2328
3251
|
glb.DEBUG_INFO_OBJ = {};
|
|
2329
3252
|
// var CONNECTION_ATTEMPTS = 0;
|
|
2330
3253
|
glb.APP_INFO = {};
|