@xuda.io/runtime-bundle 1.0.1434 → 1.0.1436

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.
@@ -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 typeof window !== 'undefined';
92
+ return !!func.runtime.platform.get_window();
126
93
  },
127
94
  has_document: function () {
128
- return typeof document !== 'undefined';
95
+ return !!func.runtime.platform.get_document();
129
96
  },
130
97
  get_window: function () {
131
- if (func.runtime.platform.has_window()) {
132
- return window;
133
- }
134
- return null;
98
+ return func.runtime.platform.get_global('window');
135
99
  },
136
100
  get_document: function () {
137
- if (func.runtime.platform.has_document()) {
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
- if (typeof navigator !== 'undefined') {
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
- if (typeof HTMLElement === 'undefined') {
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 HTMLElement;
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
- if (type === 'session') {
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
  }
@@ -196,6 +153,23 @@ func.runtime.platform = {
196
153
  return false;
197
154
  }
198
155
  },
156
+ get_cookie_item: function (key) {
157
+ if (!key) {
158
+ return null;
159
+ }
160
+ const doc = func.runtime.platform.get_document();
161
+ const cookie_string = doc?.cookie;
162
+ if (!cookie_string) {
163
+ return null;
164
+ }
165
+ const cookie_entry = cookie_string.split('; ').find(function (cookie) {
166
+ return cookie.startsWith(key + '=');
167
+ });
168
+ if (!cookie_entry) {
169
+ return null;
170
+ }
171
+ return cookie_entry.split('=').slice(1).join('=') || null;
172
+ },
199
173
  get_url_href: function () {
200
174
  return func.runtime.platform.get_location()?.href || '';
201
175
  },
@@ -308,9 +282,8 @@ func.runtime.platform.emit = function (name, data) {
308
282
  handlers[i](data);
309
283
  }
310
284
  }
311
- // also fire on DOM if in browser (for backward compatibility with custom event listeners)
312
- if (func.runtime.platform.has_document()) {
313
- 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);
314
287
  }
315
288
  } finally {
316
289
  func.runtime.platform._emitting[name] = false;
@@ -319,34 +292,41 @@ func.runtime.platform.emit = function (name, data) {
319
292
 
320
293
  // ── Platform helpers for DOM-independent resource loading ──
321
294
  func.runtime.platform.load_script = function (url, type, callback) {
322
- if (typeof document !== 'undefined') {
323
- const script = document.createElement('script');
324
- script.src = url;
325
- if (type) script.type = type;
326
- script.onload = callback;
327
- document.head.appendChild(script);
328
- } else if (callback) {
329
- callback();
295
+ const doc = func.runtime.platform.get_document();
296
+ if (!doc?.createElement || !doc?.head?.appendChild) {
297
+ if (callback) {
298
+ callback();
299
+ }
300
+ return;
330
301
  }
302
+ const script = doc.createElement('script');
303
+ script.src = url;
304
+ if (type) script.type = type;
305
+ script.onload = callback;
306
+ doc.head.appendChild(script);
331
307
  };
332
308
  func.runtime.platform.load_css = function (href) {
333
- if (typeof document === 'undefined') return;
309
+ const doc = func.runtime.platform.get_document();
310
+ if (!doc?.createElement || !doc?.head) {
311
+ return;
312
+ }
334
313
  try {
335
- if (document.querySelector('link[href="' + href + '"]')) return;
314
+ if (doc.querySelector('link[href="' + href + '"]')) return;
336
315
  } catch (err) {
337
316
  return;
338
317
  }
339
- const link = document.createElement('link');
318
+ const link = doc.createElement('link');
340
319
  link.rel = 'stylesheet';
341
320
  link.type = 'text/css';
342
321
  link.href = href;
343
- document.head.insertBefore(link, document.head.firstChild);
322
+ doc.head.insertBefore(link, doc.head.firstChild);
344
323
  };
345
324
  func.runtime.platform.remove_js_css = function (filename, filetype) {
346
- if (typeof document === 'undefined') return;
325
+ const doc = func.runtime.platform.get_document();
326
+ if (!doc?.getElementsByTagName) return;
347
327
  const tagName = filetype === 'js' ? 'script' : filetype === 'css' ? 'link' : 'none';
348
328
  const attr = filetype === 'js' ? 'src' : filetype === 'css' ? 'href' : 'none';
349
- const elements = document.getElementsByTagName(tagName);
329
+ const elements = doc.getElementsByTagName(tagName);
350
330
  for (let i = elements.length - 1; i >= 0; i--) {
351
331
  if (elements[i] && elements[i].getAttribute(attr) != null && elements[i].getAttribute(attr).indexOf(filename) !== -1) {
352
332
  elements[i].parentNode.removeChild(elements[i]);
@@ -354,15 +334,17 @@ func.runtime.platform.remove_js_css = function (filename, filetype) {
354
334
  }
355
335
  };
356
336
  func.runtime.platform.inject_css = function (cssText) {
357
- if (typeof document === 'undefined' || !cssText) return;
358
- const style = document.createElement('style');
337
+ const doc = func.runtime.platform.get_document();
338
+ if (!doc?.createElement || !doc?.head?.appendChild || !cssText) return;
339
+ const style = doc.createElement('style');
359
340
  style.type = 'text/css';
360
341
  style.textContent = cssText;
361
- document.head.appendChild(style);
342
+ doc.head.appendChild(style);
362
343
  };
363
344
  func.runtime.platform.set_title = function (title) {
364
- if (typeof document !== 'undefined') {
365
- document.title = title;
345
+ const doc = func.runtime.platform.get_document();
346
+ if (doc) {
347
+ doc.title = title;
366
348
  }
367
349
  };
368
350
  func.runtime.platform.set_cursor = function (element, cursor) {
@@ -1050,12 +1032,36 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
1050
1032
  func.runtime.resources.get_plugin_manifest_entry = function (_session, plugin_name) {
1051
1033
  return APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name] || null;
1052
1034
  };
1053
- func.runtime.resources.get_plugin_module_path = function (plugin, resource) {
1035
+ func.runtime.resources.get_plugin_resource_candidates = function (_session, plugin, resource) {
1054
1036
  const manifest_entry = plugin?.manifest?.[resource];
1055
- return `${manifest_entry?.dist ? 'dist/' : ''}${resource}`;
1037
+ const default_path = `${manifest_entry?.dist ? 'dist/' : ''}${resource}`;
1038
+ const candidates = [];
1039
+ if (_session?.worker_type === 'Dev' && manifest_entry?.dist && /\.mjs$/.test(resource)) {
1040
+ candidates.push(`src/${resource}`);
1041
+ }
1042
+ candidates.push(default_path);
1043
+ return Array.from(new Set(candidates.filter(Boolean)));
1044
+ };
1045
+ func.runtime.resources.get_plugin_module_path = function (plugin, resource, _session) {
1046
+ return func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource)[0] || resource;
1056
1047
  };
1057
1048
  func.runtime.resources.get_plugin_module_url = async function (SESSION_ID, plugin_name, plugin, resource) {
1058
- return await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, func.runtime.resources.get_plugin_module_path(plugin, resource));
1049
+ const _session = SESSION_OBJ[SESSION_ID];
1050
+ return await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, func.runtime.resources.get_plugin_module_path(plugin, resource, _session));
1051
+ };
1052
+ func.runtime.resources.import_plugin_module = async function (SESSION_ID, plugin_name, plugin, resource) {
1053
+ const _session = SESSION_OBJ[SESSION_ID];
1054
+ const candidates = func.runtime.resources.get_plugin_resource_candidates(_session, plugin, resource);
1055
+ let last_error = null;
1056
+ for (let index = 0; index < candidates.length; index++) {
1057
+ const candidate = candidates[index];
1058
+ try {
1059
+ return await func.utils.get_plugin_resource(SESSION_ID, plugin_name, candidate);
1060
+ } catch (error) {
1061
+ last_error = error;
1062
+ }
1063
+ }
1064
+ throw last_error || new Error(`plugin resource not found: ${plugin_name}/${resource}`);
1059
1065
  };
1060
1066
  func.runtime.resources.load_plugin_runtime_css = async function (SESSION_ID, plugin_name, plugin) {
1061
1067
  if (!plugin?.manifest?.['runtime.mjs']?.dist || !plugin?.manifest?.['runtime.mjs']?.css) {
@@ -1085,12 +1091,10 @@ func.runtime.resources.run_ui_plugin = async function (SESSION_ID, paramsP, $elm
1085
1091
 
1086
1092
  await func.runtime.resources.load_plugin_runtime_css(SESSION_ID, plugin_name, plugin);
1087
1093
 
1088
- const plugin_index_src = await func.runtime.resources.get_plugin_module_url(SESSION_ID, plugin_name, plugin, 'index.mjs');
1089
- const plugin_index_resources = await import(plugin_index_src);
1094
+ const plugin_index_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'index.mjs');
1090
1095
  const properties = await func.runtime.resources.resolve_plugin_properties(SESSION_ID, paramsP.dsSessionP, value?.attributes, plugin_index_resources.properties);
1091
1096
 
1092
- const plugin_runtime_src = await func.runtime.resources.get_plugin_module_url(SESSION_ID, plugin_name, plugin, 'runtime.mjs');
1093
- const plugin_runtime_resources = await import(plugin_runtime_src);
1097
+ const plugin_runtime_resources = await func.runtime.resources.import_plugin_module(SESSION_ID, plugin_name, plugin, 'runtime.mjs');
1094
1098
 
1095
1099
  if (plugin_runtime_resources.cdn && Array.isArray(plugin_runtime_resources.cdn)) {
1096
1100
  for await (const resource of plugin_runtime_resources.cdn) {
@@ -1173,25 +1177,52 @@ func.runtime.widgets.get_fields_data = async function (context, fields, props) {
1173
1177
 
1174
1178
  return { code: return_code, data: data_obj };
1175
1179
  };
1180
+ func.runtime.widgets.get_resource_candidates = function (context, resource) {
1181
+ return func.runtime.resources.get_plugin_resource_candidates(context._session, context.plugin, resource);
1182
+ };
1183
+ func.runtime.widgets.normalize_capabilities = function (definition) {
1184
+ const capabilities = definition?.capabilities || {};
1185
+ return {
1186
+ browser: capabilities.browser !== false,
1187
+ headless: capabilities.headless === true,
1188
+ };
1189
+ };
1190
+ func.runtime.widgets.supports_current_environment = function (definition) {
1191
+ const capabilities = func.runtime.widgets.normalize_capabilities(definition);
1192
+ if (func.runtime.platform.has_document()) {
1193
+ return capabilities.browser !== false;
1194
+ }
1195
+ return !!capabilities.headless;
1196
+ };
1176
1197
  func.runtime.widgets.get_resource_path = function (context, resource) {
1198
+ const relative_path = func.runtime.widgets.get_resource_candidates(context, resource)[0] || resource;
1177
1199
  if (context._session.worker_type === 'Dev') {
1178
- return `../../plugins/${context.plugin_name}/${resource}`;
1200
+ return `../../plugins/${context.plugin_name}/${relative_path}`;
1179
1201
  }
1180
- const manifest_entry = context.plugin?.manifest?.[resource];
1181
- const dist_prefix = manifest_entry?.dist ? 'dist/' : '';
1182
- return `https://${context._session.domain}/plugins/${context.plugin_name}/${dist_prefix}${resource}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
1202
+ return `https://${context._session.domain}/plugins/${context.plugin_name}/${relative_path}?gtp_token=${context._session.gtp_token}&app_id=${context._session.app_id}`;
1183
1203
  };
1184
1204
  func.runtime.widgets.load_css_style = function (context) {
1185
1205
  func.utils.load_css_on_demand(func.runtime.widgets.get_resource_path(context, 'style.css'));
1186
1206
  return true;
1187
1207
  };
1188
1208
  func.runtime.widgets.get_resource = async function (context, resource) {
1189
- const manifest_entry = context.plugin?.manifest?.[resource];
1190
- const path = `${manifest_entry?.dist ? 'dist/' : ''}${resource}`;
1191
- return await func.utils.get_plugin_resource(context.SESSION_ID, context.plugin_name, path);
1209
+ const candidates = func.runtime.widgets.get_resource_candidates(context, resource);
1210
+ let last_error = null;
1211
+ for (let index = 0; index < candidates.length; index++) {
1212
+ const candidate = candidates[index];
1213
+ try {
1214
+ return await func.utils.get_plugin_resource(context.SESSION_ID, context.plugin_name, candidate);
1215
+ } catch (error) {
1216
+ last_error = error;
1217
+ }
1218
+ }
1219
+ throw last_error || new Error(`widget resource not found: ${context.plugin_name}/${resource}`);
1220
+ };
1221
+ func.runtime.widgets.get_definition = async function (context) {
1222
+ return await func.runtime.widgets.get_resource(context, 'index.mjs');
1192
1223
  };
1193
1224
  func.runtime.widgets.get_methods = async function (context) {
1194
- const index = await func.runtime.widgets.get_resource(context, 'index.mjs');
1225
+ const index = await func.runtime.widgets.get_definition(context);
1195
1226
  return index?.methods || {};
1196
1227
  };
1197
1228
  func.runtime.widgets.load_runtime_css = async function (context) {
@@ -1202,7 +1233,7 @@ func.runtime.widgets.load_runtime_css = async function (context) {
1202
1233
  func.utils.load_css_on_demand(plugin_runtime_css_url);
1203
1234
  return true;
1204
1235
  };
1205
- func.runtime.widgets.build_params = function (context, $containerP, plugin_setup, api_utils, extra = {}) {
1236
+ func.runtime.widgets.build_params = function (context, container_node, container_data, plugin_setup, api_utils, extra = {}) {
1206
1237
  return {
1207
1238
  SESSION_ID: context.SESSION_ID,
1208
1239
  method: context.method,
@@ -1211,14 +1242,28 @@ func.runtime.widgets.build_params = function (context, $containerP, plugin_setup
1211
1242
  sourceP: context.sourceP,
1212
1243
  propsP: context.propsP,
1213
1244
  plugin_name: context.plugin_name,
1214
- $containerP,
1245
+ container_node,
1246
+ container_data,
1215
1247
  plugin_setup,
1216
1248
  report_error: function (descP, warn) {
1217
1249
  return func.runtime.widgets.report_error(context, descP, warn);
1218
1250
  },
1251
+ log_error: function (descP, warn) {
1252
+ return func.runtime.widgets.report_error(context, descP, warn);
1253
+ },
1219
1254
  call_plugin_api: async function (plugin_nameP, dataP) {
1220
1255
  return await func.utils.call_plugin_api(context.SESSION_ID, plugin_nameP, dataP);
1221
1256
  },
1257
+ set_SYS_GLOBAL_OBJ_WIDGET_INFO: async function (docP) {
1258
+ return await func.utils.set_SYS_GLOBAL_OBJ_WIDGET_INFO(context.SESSION_ID, docP);
1259
+ },
1260
+ run_widgetCallbackEvent: async function () {
1261
+ const event_id = context.propsP?.widgetCallbackEvent;
1262
+ if (!event_id || !api_utils?.invoke_event) {
1263
+ return false;
1264
+ }
1265
+ return await api_utils.invoke_event(event_id);
1266
+ },
1222
1267
  api_utils,
1223
1268
  ...extra,
1224
1269
  };
@@ -2549,6 +2594,9 @@ func.runtime.ui.get_meta_by_element_id = function (element_id) {
2549
2594
  func.runtime.ui.find_element_by_id = function () {
2550
2595
  return null;
2551
2596
  };
2597
+ func.runtime.ui.get_parent_element_id = function () {
2598
+ return null;
2599
+ };
2552
2600
  func.runtime.ui.get_session_root = function () {
2553
2601
  return null;
2554
2602
  };
@@ -2606,8 +2654,30 @@ func.runtime.ui.get_children = function (target) {
2606
2654
  if (target?._v_id) return target.children.slice();
2607
2655
  return [];
2608
2656
  };
2657
+ func.runtime.ui._wrap_matches = function (matches) {
2658
+ if (!matches) matches = [];
2659
+ const result = {
2660
+ length: matches.length,
2661
+ toArray: function () { return matches.slice(); },
2662
+ };
2663
+ for (let i = 0; i < matches.length; i++) {
2664
+ result[i] = matches[i];
2665
+ }
2666
+ result[Symbol.iterator] = function () {
2667
+ let idx = 0;
2668
+ return {
2669
+ next: function () {
2670
+ if (idx < matches.length) {
2671
+ return { value: matches[idx++], done: false };
2672
+ }
2673
+ return { done: true };
2674
+ },
2675
+ };
2676
+ };
2677
+ return result;
2678
+ };
2609
2679
  func.runtime.ui.find_by_selector = function () {
2610
- return { length: 0, toArray: function () { return []; } };
2680
+ return func.runtime.ui._wrap_matches([]);
2611
2681
  };
2612
2682
  func.runtime.ui.insert_before = function ($element) { return $element; };
2613
2683
  func.runtime.ui.insert_after = function ($element) { return $element; };
@@ -2717,6 +2787,9 @@ func.runtime.ui.remove_xu_ui = function (xu_ui_id) {
2717
2787
  func.runtime.ui.delete_meta(xu_ui_id);
2718
2788
  return true;
2719
2789
  };
2790
+ func.runtime.ui.find_xu_ui_in_root = function () {
2791
+ return func.runtime.ui._wrap_matches([]);
2792
+ };
2720
2793
  func.runtime.ui.build_debug_info = function (nodeP, $container, items) {
2721
2794
  const container_data = func.runtime.ui.get_data($container);
2722
2795
  return {
@@ -2818,13 +2891,24 @@ func.runtime.ui.build_xu_ui_id_seed = function (nodeP, dsSessionP, key_path, cur
2818
2891
  const elem_key = `${nodeId}-${key_path}-${currentRecordId}`;
2819
2892
  return `${nodeP.id}-${elem_key}-${dsSessionP?.toString() || ''}`;
2820
2893
  };
2894
+ func.runtime.ui.build_container_key_path = function (container_xu_data, keyP, parent_infoP, nodeP, parent_nodeP) {
2895
+ const key_segment = typeof keyP === 'undefined' || keyP === null ? '0' : `${keyP}`;
2896
+ let key_path = `${container_xu_data?.key_path || '0'}-${key_segment}`;
2897
+ const parent_identity = parent_nodeP?.xu_tree_id || parent_nodeP?.id;
2898
+ const node_identity = nodeP?.xu_tree_id || nodeP?.id;
2899
+ const is_iterated_clone = !!(parent_infoP?.iterate_info && parent_identity && node_identity && parent_identity === node_identity);
2900
+ if (is_iterated_clone) {
2901
+ key_path += '-iter';
2902
+ }
2903
+ return key_path;
2904
+ };
2821
2905
  func.runtime.ui.generate_xu_ui_id = async function (SESSION_ID, nodeP, $container, paramsP, keyP, precomputed) {
2822
2906
  precomputed = precomputed || {};
2823
2907
  const dsSessionP = paramsP.dsSessionP;
2824
2908
  const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];
2825
2909
  const containerXuData = precomputed.container_xu_data || func.runtime.ui.get_data($container)?.xuData;
2826
2910
  const currentRecordId = typeof precomputed.currentRecordId !== 'undefined' ? precomputed.currentRecordId : containerXuData?.recordid || _ds?.currentRecordId || '';
2827
- const key_path = precomputed.key_path || `${containerXuData?.key_path || '0'}-${keyP || '0'}`;
2911
+ const key_path = precomputed.key_path || func.runtime.ui.build_container_key_path(containerXuData, keyP, precomputed.parent_infoP, nodeP, precomputed.parent_nodeP);
2828
2912
  const ui_id = func.runtime.ui.build_xu_ui_id_seed(nodeP, dsSessionP, key_path, currentRecordId);
2829
2913
 
2830
2914
  if (func.runtime.ui.ui_id_hash_cache.has(ui_id)) {
@@ -2846,13 +2930,15 @@ func.runtime.ui.create_container = async function (options) {
2846
2930
  const currentRecordId = container_xu_data?.recordid || (_ds ? _ds.currentRecordId : '');
2847
2931
 
2848
2932
  try {
2849
- const key_path = `${container_xu_data?.key_path || '0'}-${options.keyP || '0'}`;
2933
+ const key_path = func.runtime.ui.build_container_key_path(container_xu_data, options.keyP, options.parent_infoP, options.nodeP, options.parent_nodeP);
2850
2934
  const elem_key = `${options.nodeP.xu_tree_id || options.nodeP.id}-${key_path}-${currentRecordId}`;
2851
2935
  const $div = func.runtime.ui.create_container_element(options.div_typeP);
2852
2936
  const new_ui_id = await func.runtime.ui.generate_xu_ui_id(options.SESSION_ID, options.nodeP, options.$container, options.paramsP, options.keyP, {
2853
2937
  container_xu_data,
2854
2938
  currentRecordId,
2855
2939
  key_path,
2940
+ parent_infoP: options.parent_infoP,
2941
+ parent_nodeP: options.parent_nodeP,
2856
2942
  });
2857
2943
 
2858
2944
  func.runtime.ui.apply_container_meta($div, {
@@ -4609,8 +4695,9 @@ func.datasource.clean = function (SESSION_ID, screenIdP) {
4609
4695
  var arr = [];
4610
4696
  for (const [key, val] of Object.entries(SESSION_OBJ[SESSION_ID].DS_GLB)) {
4611
4697
  try {
4612
- const _screen_el = val.screenId ? document.getElementById(val.screenId) : null;
4613
- const screen_parent_id = _screen_el?.parentElement?.id || null;
4698
+ const screen_parent_id = val.screenId && func.runtime?.ui?.get_parent_element_id
4699
+ ? func.runtime.ui.get_parent_element_id(val.screenId)
4700
+ : null;
4614
4701
  if (
4615
4702
  Number(key) > 0 &&
4616
4703
  (val.screenId === screenIdP ||
@@ -4619,7 +4706,7 @@ func.datasource.clean = function (SESSION_ID, screenIdP) {
4619
4706
  (val && val.parentDataSourceNo && arr.includes(val.parentDataSourceNo.toString())))
4620
4707
  ) {
4621
4708
  arr.push(key);
4622
- if (val.screenId) func.UI.utils.screen_blocker(false, val.screenId);
4709
+ if (val.screenId && func.UI?.utils?.screen_blocker) func.UI.utils.screen_blocker(false, val.screenId);
4623
4710
  }
4624
4711
  } catch (err) {
4625
4712
  console.warn('func.datasource.clean failed');
@@ -8722,6 +8809,7 @@ func.events.execute = async function (
8722
8809
  },
8723
8810
  execute_native_javascript: async function () {
8724
8811
  const module = await func.common.get_module(SESSION_ID, 'xuda-event-javascript-module.mjs');
8812
+ const resolved_element_expr = `(func.runtime.ui && func.runtime.ui.find_xu_ui_in_root && func.runtime.ui.get_first_node ? func.runtime.ui.get_first_node(func.runtime.ui.find_xu_ui_in_root(SESSION_ID, ${JSON.stringify(elementP)})) : null)`;
8725
8813
 
8726
8814
  const result = await module.run_javascript(
8727
8815
  SESSION_ID,
@@ -8729,7 +8817,7 @@ func.events.execute = async function (
8729
8817
  dsSession,
8730
8818
  `(async function(el,evt) {
8731
8819
  ${refIdP.value}
8732
- })(document.querySelector(\`[xu-ui-id="${elementP}"]\`),evt)`,
8820
+ })(${resolved_element_expr},evt)`,
8733
8821
  null,
8734
8822
  null,
8735
8823
  null,
@@ -8742,6 +8830,7 @@ func.events.execute = async function (
8742
8830
  },
8743
8831
  execute_evaluate_javascript: async function () {
8744
8832
  const module = await func.common.get_module(SESSION_ID, 'xuda-event-javascript-module.mjs');
8833
+ const resolved_element_expr = `(func.runtime.ui && func.runtime.ui.find_xu_ui_in_root && func.runtime.ui.get_first_node ? func.runtime.ui.get_first_node(func.runtime.ui.find_xu_ui_in_root(SESSION_ID, ${JSON.stringify(elementP)})) : null)`;
8745
8834
 
8746
8835
  const result = await module.run_javascript(
8747
8836
  SESSION_ID,
@@ -8749,7 +8838,7 @@ func.events.execute = async function (
8749
8838
  dsSession,
8750
8839
  `(async function(el,evt) {
8751
8840
  ${refIdP.value}
8752
- })(document.querySelector(\`[xu-ui-id="${elementP}"]\`),evt)`,
8841
+ })(${resolved_element_expr},evt)`,
8753
8842
  true,
8754
8843
  null,
8755
8844
  null,