@xuda.io/xuda-worker-bundle 1.3.2694 → 1.3.2696

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.
Files changed (2) hide show
  1. package/index.js +207 -8
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -291,7 +291,30 @@ func.runtime.platform.emit = function (name, data) {
291
291
  };
292
292
 
293
293
  // ── Platform helpers for DOM-independent resource loading ──
294
- func.runtime.platform.load_script = function (url, type, callback) {
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) {
295
318
  const doc = func.runtime.platform.get_document();
296
319
  if (!doc?.createElement || !doc?.head?.appendChild) {
297
320
  if (callback) {
@@ -299,19 +322,63 @@ func.runtime.platform.load_script = function (url, type, callback) {
299
322
  }
300
323
  return;
301
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
+
302
349
  const script = doc.createElement('script');
303
350
  script.src = url;
304
351
  if (type) script.type = type;
305
- script.onload = callback;
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
+ };
306
364
  doc.head.appendChild(script);
365
+ return script;
307
366
  };
308
- func.runtime.platform.load_css = function (href) {
367
+ func.runtime.platform.load_css = function (href, attributes) {
309
368
  const doc = func.runtime.platform.get_document();
310
369
  if (!doc?.createElement || !doc?.head) {
311
370
  return;
312
371
  }
313
372
  try {
314
- if (doc.querySelector('link[href="' + href + '"]')) return;
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;
315
382
  } catch (err) {
316
383
  return;
317
384
  }
@@ -319,7 +386,9 @@ func.runtime.platform.load_css = function (href) {
319
386
  link.rel = 'stylesheet';
320
387
  link.type = 'text/css';
321
388
  link.href = href;
389
+ func.runtime.platform.apply_element_attributes(link, attributes, ['href']);
322
390
  doc.head.insertBefore(link, doc.head.firstChild);
391
+ return link;
323
392
  };
324
393
  func.runtime.platform.remove_js_css = function (filename, filetype) {
325
394
  const doc = func.runtime.platform.get_document();
@@ -353,6 +422,128 @@ func.runtime.platform.set_cursor = function (element, cursor) {
353
422
  node.style.cursor = cursor;
354
423
  }
355
424
  };
425
+ func.runtime.program.normalize_doc_for_runtime = function (doc) {
426
+ if (!doc || doc.__xudaRuntimeNormalized || !Array.isArray(doc.progUi) || !doc.progUi.length) {
427
+ return doc;
428
+ }
429
+
430
+ const normalize_tag_name = function (tag_name) {
431
+ return `${tag_name || ''}`.trim().toLowerCase();
432
+ };
433
+ const merge_attributes = function (target, source) {
434
+ const merged = { ...(target || {}) };
435
+ const source_attributes = source || {};
436
+ const keys = Object.keys(source_attributes);
437
+
438
+ for (let index = 0; index < keys.length; index++) {
439
+ const key = keys[index];
440
+ const value = source_attributes[key];
441
+ if (typeof value === 'undefined') {
442
+ continue;
443
+ }
444
+
445
+ if (key === 'class' && merged.class && value) {
446
+ const next_value = `${merged.class} ${value}`.trim();
447
+ merged.class = Array.from(new Set(next_value.split(/\s+/).filter(Boolean))).join(' ');
448
+ continue;
449
+ }
450
+
451
+ if (key === 'style' && merged.style && value) {
452
+ merged.style = `${merged.style}; ${value}`.trim();
453
+ continue;
454
+ }
455
+
456
+ if (typeof merged[key] === 'undefined') {
457
+ merged[key] = value;
458
+ }
459
+ }
460
+
461
+ return merged;
462
+ };
463
+ const normalize_nodes = function (nodes, state) {
464
+ const normalized_nodes = [];
465
+
466
+ for (let index = 0; index < (nodes || []).length; index++) {
467
+ const node = nodes[index];
468
+ if (!node || typeof node !== 'object') {
469
+ continue;
470
+ }
471
+
472
+ const tag_name = normalize_tag_name(node.tagName);
473
+
474
+ if (tag_name === '!doctype') {
475
+ state.changed = true;
476
+ continue;
477
+ }
478
+
479
+ if (tag_name === 'html') {
480
+ state.changed = true;
481
+ state.root_attributes = merge_attributes(state.root_attributes, node.attributes);
482
+ normalized_nodes.push.apply(normalized_nodes, normalize_nodes(node.children, state));
483
+ continue;
484
+ }
485
+
486
+ if (tag_name === 'head') {
487
+ state.changed = true;
488
+ normalized_nodes.push.apply(normalized_nodes, normalize_nodes(node.children, state));
489
+ continue;
490
+ }
491
+
492
+ if (tag_name === 'body') {
493
+ state.changed = true;
494
+ state.root_attributes = merge_attributes(state.root_attributes, node.attributes);
495
+ normalized_nodes.push.apply(normalized_nodes, normalize_nodes(node.children, state));
496
+ continue;
497
+ }
498
+
499
+ let next_node = node;
500
+ if (Array.isArray(node.children) && node.children.length) {
501
+ const next_children = normalize_nodes(node.children, state);
502
+ if (next_children !== node.children) {
503
+ next_node = {
504
+ ...node,
505
+ children: next_children,
506
+ };
507
+ state.changed = true;
508
+ }
509
+ }
510
+
511
+ normalized_nodes.push(next_node);
512
+ }
513
+
514
+ return normalized_nodes;
515
+ };
516
+
517
+ const [root_node, ...extra_nodes] = doc.progUi;
518
+ if (!root_node || typeof root_node !== 'object') {
519
+ return doc;
520
+ }
521
+
522
+ const state = {
523
+ changed: false,
524
+ root_attributes: {},
525
+ };
526
+
527
+ const normalized_children = normalize_nodes([...(root_node.children || []), ...extra_nodes], state);
528
+ const merged_attributes = merge_attributes(root_node.attributes, state.root_attributes);
529
+
530
+ if (!state.changed && !Object.keys(state.root_attributes).length) {
531
+ doc.__xudaRuntimeNormalized = true;
532
+ return doc;
533
+ }
534
+
535
+ return {
536
+ ...doc,
537
+ __xudaRuntimeNormalized: true,
538
+ progUi: [
539
+ {
540
+ ...root_node,
541
+ attributes: merged_attributes,
542
+ children: normalized_children,
543
+ },
544
+ ],
545
+ };
546
+ };
356
547
 
357
548
  func.runtime.env = {
358
549
  get_url_params: function () {
@@ -1154,10 +1345,10 @@ func.runtime.resources.load_cdn = async function (SESSION_ID, resource) {
1154
1345
  await func.utils.load_js_on_demand(normalized_resource.src);
1155
1346
  break;
1156
1347
  case 'css':
1157
- await func.utils.load_js_on_demand(normalized_resource.src);
1348
+ func.runtime.platform.load_css(normalized_resource.src);
1158
1349
  break;
1159
1350
  case 'module':
1160
- func.utils.load_js_on_demand(normalized_resource.src, 'module');
1351
+ await func.utils.load_js_on_demand(normalized_resource.src, 'module');
1161
1352
  break;
1162
1353
  default:
1163
1354
  await func.utils.load_js_on_demand(normalized_resource.src);
@@ -6886,6 +7077,13 @@ func.utils.DOCS_OBJ = {};
6886
7077
  func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
6887
7078
  if (!idP || idP === '0') return;
6888
7079
 
7080
+ const normalize_runtime_doc = function (doc) {
7081
+ if (!doc || !func.runtime.program?.normalize_doc_for_runtime) {
7082
+ return doc;
7083
+ }
7084
+ return func.runtime.program.normalize_doc_for_runtime(doc);
7085
+ };
7086
+
6889
7087
  var _session = SESSION_OBJ[SESSION_ID];
6890
7088
  const _app_id = _session.app_id;
6891
7089
  if (!DOCS_OBJ[_app_id]) {
@@ -6907,7 +7105,8 @@ func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
6907
7105
  }
6908
7106
  let val = _session.project_data?.programs?.[idP];
6909
7107
  if (val) {
6910
- return (DOCS_OBJ[_app_id][idP] = val);
7108
+ DOCS_OBJ[_app_id][idP] = normalize_runtime_doc(val);
7109
+ return DOCS_OBJ[_app_id][idP];
6911
7110
  }
6912
7111
  }
6913
7112
 
@@ -6915,7 +7114,7 @@ func.utils.DOCS_OBJ.get = async function (SESSION_ID, idP) {
6915
7114
  const module = await func.common.get_module(SESSION_ID, `xuda-progs-loader-module.mjs`);
6916
7115
 
6917
7116
  if (idP !== 'system') {
6918
- DOCS_OBJ[_app_id][idP] = await module.DOCS_OBJ_get(SESSION_ID, idP);
7117
+ DOCS_OBJ[_app_id][idP] = normalize_runtime_doc(await module.DOCS_OBJ_get(SESSION_ID, idP));
6919
7118
  if (DOCS_OBJ[_app_id][idP] && xu_isEmpty(DOCS_OBJ[_app_id][idP])) {
6920
7119
  await func.utils.remove_cached_objects(SESSION_ID);
6921
7120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/xuda-worker-bundle",
3
- "version": "1.3.2694",
3
+ "version": "1.3.2696",
4
4
  "description": "xuda framework",
5
5
  "main": "index.js",
6
6
  "scripts": {