@xuda.io/runtime-bundle 1.0.1437 → 1.0.1439

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.
@@ -1836,6 +1836,128 @@ func.runtime.platform.set_cursor = function (element, cursor) {
1836
1836
  node.style.cursor = cursor;
1837
1837
  }
1838
1838
  };
1839
+ func.runtime.program.normalize_doc_for_runtime = function (doc) {
1840
+ if (!doc || doc.__xudaRuntimeNormalized || !Array.isArray(doc.progUi) || !doc.progUi.length) {
1841
+ return doc;
1842
+ }
1843
+
1844
+ const normalize_tag_name = function (tag_name) {
1845
+ return `${tag_name || ''}`.trim().toLowerCase();
1846
+ };
1847
+ const merge_attributes = function (target, source) {
1848
+ const merged = { ...(target || {}) };
1849
+ const source_attributes = source || {};
1850
+ const keys = Object.keys(source_attributes);
1851
+
1852
+ for (let index = 0; index < keys.length; index++) {
1853
+ const key = keys[index];
1854
+ const value = source_attributes[key];
1855
+ if (typeof value === 'undefined') {
1856
+ continue;
1857
+ }
1858
+
1859
+ if (key === 'class' && merged.class && value) {
1860
+ const next_value = `${merged.class} ${value}`.trim();
1861
+ merged.class = Array.from(new Set(next_value.split(/\s+/).filter(Boolean))).join(' ');
1862
+ continue;
1863
+ }
1864
+
1865
+ if (key === 'style' && merged.style && value) {
1866
+ merged.style = `${merged.style}; ${value}`.trim();
1867
+ continue;
1868
+ }
1869
+
1870
+ if (typeof merged[key] === 'undefined') {
1871
+ merged[key] = value;
1872
+ }
1873
+ }
1874
+
1875
+ return merged;
1876
+ };
1877
+ const normalize_nodes = function (nodes, state) {
1878
+ const normalized_nodes = [];
1879
+
1880
+ for (let index = 0; index < (nodes || []).length; index++) {
1881
+ const node = nodes[index];
1882
+ if (!node || typeof node !== 'object') {
1883
+ continue;
1884
+ }
1885
+
1886
+ const tag_name = normalize_tag_name(node.tagName);
1887
+
1888
+ if (tag_name === '!doctype') {
1889
+ state.changed = true;
1890
+ continue;
1891
+ }
1892
+
1893
+ if (tag_name === 'html') {
1894
+ state.changed = true;
1895
+ state.root_attributes = merge_attributes(state.root_attributes, node.attributes);
1896
+ normalized_nodes.push.apply(normalized_nodes, normalize_nodes(node.children, state));
1897
+ continue;
1898
+ }
1899
+
1900
+ if (tag_name === 'head') {
1901
+ state.changed = true;
1902
+ normalized_nodes.push.apply(normalized_nodes, normalize_nodes(node.children, state));
1903
+ continue;
1904
+ }
1905
+
1906
+ if (tag_name === 'body') {
1907
+ state.changed = true;
1908
+ state.root_attributes = merge_attributes(state.root_attributes, node.attributes);
1909
+ normalized_nodes.push.apply(normalized_nodes, normalize_nodes(node.children, state));
1910
+ continue;
1911
+ }
1912
+
1913
+ let next_node = node;
1914
+ if (Array.isArray(node.children) && node.children.length) {
1915
+ const next_children = normalize_nodes(node.children, state);
1916
+ if (next_children !== node.children) {
1917
+ next_node = {
1918
+ ...node,
1919
+ children: next_children,
1920
+ };
1921
+ state.changed = true;
1922
+ }
1923
+ }
1924
+
1925
+ normalized_nodes.push(next_node);
1926
+ }
1927
+
1928
+ return normalized_nodes;
1929
+ };
1930
+
1931
+ const [root_node, ...extra_nodes] = doc.progUi;
1932
+ if (!root_node || typeof root_node !== 'object') {
1933
+ return doc;
1934
+ }
1935
+
1936
+ const state = {
1937
+ changed: false,
1938
+ root_attributes: {},
1939
+ };
1940
+
1941
+ const normalized_children = normalize_nodes([...(root_node.children || []), ...extra_nodes], state);
1942
+ const merged_attributes = merge_attributes(root_node.attributes, state.root_attributes);
1943
+
1944
+ if (!state.changed && !Object.keys(state.root_attributes).length) {
1945
+ doc.__xudaRuntimeNormalized = true;
1946
+ return doc;
1947
+ }
1948
+
1949
+ return {
1950
+ ...doc,
1951
+ __xudaRuntimeNormalized: true,
1952
+ progUi: [
1953
+ {
1954
+ ...root_node,
1955
+ attributes: merged_attributes,
1956
+ children: normalized_children,
1957
+ },
1958
+ ],
1959
+ };
1960
+ };
1839
1961
 
1840
1962
  func.runtime.env = {
1841
1963
  get_url_params: function () {
@@ -7951,6 +8073,13 @@ func.utils.DOCS_OBJ = {};
7951
8073
  func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
7952
8074
  if (!idP || idP === '0') return;
7953
8075
 
8076
+ const normalize_runtime_doc = function (doc) {
8077
+ if (!doc || !func.runtime.program?.normalize_doc_for_runtime) {
8078
+ return doc;
8079
+ }
8080
+ return func.runtime.program.normalize_doc_for_runtime(doc);
8081
+ };
8082
+
7954
8083
  var _session = SESSION_OBJ[SESSION_ID];
7955
8084
  const _app_id = _session.app_id;
7956
8085
  if (!DOCS_OBJ[_app_id]) {
@@ -7972,7 +8101,8 @@ func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
7972
8101
  }
7973
8102
  let val = _session.project_data?.programs?.[idP];
7974
8103
  if (val) {
7975
- return (DOCS_OBJ[_app_id][idP] = val);
8104
+ DOCS_OBJ[_app_id][idP] = normalize_runtime_doc(val);
8105
+ return DOCS_OBJ[_app_id][idP];
7976
8106
  }
7977
8107
  }
7978
8108
 
@@ -7980,7 +8110,7 @@ func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
7980
8110
  const module = await func.common.get_module(SESSION_ID, `xuda-progs-loader-module.mjs`);
7981
8111
 
7982
8112
  if (idP !== 'system') {
7983
- DOCS_OBJ[_app_id][idP] = await module.DOCS_OBJ_get(SESSION_ID, idP);
8113
+ DOCS_OBJ[_app_id][idP] = normalize_runtime_doc(await module.DOCS_OBJ_get(SESSION_ID, idP));
7984
8114
  if (DOCS_OBJ[_app_id][idP] && xu_isEmpty(DOCS_OBJ[_app_id][idP])) {
7985
8115
  await func.utils.remove_cached_objects(SESSION_ID);
7986
8116
 
@@ -17786,6 +17916,41 @@ const create_runtime_head_element = function (doc, tag_name, attributes, asset_k
17786
17916
  return node;
17787
17917
  };
17788
17918
 
17919
+ const get_runtime_html_script_queue = function () {
17920
+ return (
17921
+ func.runtime.render._html_script_queue ||
17922
+ (func.runtime.render._html_script_queue = {
17923
+ items: [],
17924
+ running: false,
17925
+ })
17926
+ );
17927
+ };
17928
+
17929
+ const queue_runtime_html_script_task = function (task) {
17930
+ const queue = get_runtime_html_script_queue();
17931
+ queue.items.push(task);
17932
+ };
17933
+
17934
+ func.runtime.render.flush_html_script_queue = async function () {
17935
+ const queue = get_runtime_html_script_queue();
17936
+ if (queue.running || !queue.items.length) {
17937
+ return;
17938
+ }
17939
+
17940
+ queue.running = true;
17941
+
17942
+ try {
17943
+ while (queue.items.length) {
17944
+ const next_task = queue.items.shift();
17945
+ await next_task();
17946
+ }
17947
+ } catch (error) {
17948
+ console.error(error);
17949
+ } finally {
17950
+ queue.running = false;
17951
+ }
17952
+ };
17953
+
17789
17954
  const upsert_runtime_head_element = async function (options) {
17790
17955
  const doc = func.runtime.platform.get_document?.();
17791
17956
  const head = doc?.head;
@@ -17899,19 +18064,21 @@ const render_runtime_html_asset = async function (options) {
17899
18064
  if (!src && !content.trim()) {
17900
18065
  return options.$container;
17901
18066
  }
17902
- await upsert_runtime_head_element({
17903
- tag_name,
17904
- attributes,
17905
- content,
17906
- asset_key,
17907
- signature,
17908
- find_existing_attr: src
17909
- ? {
17910
- name: 'src',
17911
- value: src,
17912
- }
17913
- : null,
17914
- await_load: !!src,
18067
+ queue_runtime_html_script_task(async function () {
18068
+ await upsert_runtime_head_element({
18069
+ tag_name,
18070
+ attributes,
18071
+ content,
18072
+ asset_key,
18073
+ signature,
18074
+ find_existing_attr: src
18075
+ ? {
18076
+ name: 'src',
18077
+ value: src,
18078
+ }
18079
+ : null,
18080
+ await_load: !!src,
18081
+ });
17915
18082
  });
17916
18083
  return options.$container;
17917
18084
  }
@@ -18321,20 +18488,30 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
18321
18488
  keyP,
18322
18489
  parent_nodeP,
18323
18490
  });
18491
+ const render_depth = func.runtime.render._html_script_render_depth || (func.runtime.render._html_script_render_depth = {});
18492
+ render_depth[SESSION_ID] = (render_depth[SESSION_ID] || 0) + 1;
18324
18493
 
18325
- return await func.runtime.render.render_tree(treeP, {
18326
- SESSION_ID,
18327
- $container,
18328
- parent_infoP,
18329
- paramsP,
18330
- jobNoP,
18331
- is_skeleton,
18332
- keyP,
18333
- refreshed_ds,
18334
- parent_nodeP,
18335
- check_existP,
18336
- $root_container,
18337
- });
18494
+ try {
18495
+ return await func.runtime.render.render_tree(treeP, {
18496
+ SESSION_ID,
18497
+ $container,
18498
+ parent_infoP,
18499
+ paramsP,
18500
+ jobNoP,
18501
+ is_skeleton,
18502
+ keyP,
18503
+ refreshed_ds,
18504
+ parent_nodeP,
18505
+ check_existP,
18506
+ $root_container,
18507
+ });
18508
+ } finally {
18509
+ render_depth[SESSION_ID] = Math.max((render_depth[SESSION_ID] || 1) - 1, 0);
18510
+ if (render_depth[SESSION_ID] === 0) {
18511
+ await func.runtime.render.flush_html_script_queue?.();
18512
+ delete render_depth[SESSION_ID];
18513
+ }
18514
+ }
18338
18515
  };
18339
18516
  func.runtime = func.runtime || {};
18340
18517
  func.runtime.ui = func.runtime.ui || {};