lilact 0.3.0 → 0.5.0

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 (62) hide show
  1. package/README.md +2 -2
  2. package/bin/transpile-dir.js +2 -2
  3. package/bin/transpile.js +5 -5
  4. package/dist/lilact.development.min.js +1 -1
  5. package/dist/lilact.development.min.js.LICENSE.txt +1 -1
  6. package/dist/lilact.development.min.js.map +1 -1
  7. package/dist/lilact.production.min.js +1 -1
  8. package/dist/lilact.production.min.js.map +1 -1
  9. package/docs/assets/navigation.js +1 -1
  10. package/docs/assets/search.js +1 -1
  11. package/docs/classes/accessories.ErrorBoundary.html +8 -8
  12. package/docs/classes/accessories.Suspense.html +7 -7
  13. package/docs/classes/components.Component.html +10 -10
  14. package/docs/classes/components.HTMLComponent.html +10 -10
  15. package/docs/classes/components.RootComponent.html +10 -10
  16. package/docs/functions/components.createComponent.html +1 -1
  17. package/docs/functions/components.createRoot.html +1 -1
  18. package/docs/functions/components.render.html +1 -1
  19. package/docs/functions/jsx.transpileJSX.html +3 -3
  20. package/docs/functions/misc.classNames.html +1 -1
  21. package/docs/functions/misc.deepEqual.html +1 -1
  22. package/docs/functions/misc.getComponentByPointer.html +1 -1
  23. package/docs/functions/misc.isAsync.html +1 -1
  24. package/docs/functions/misc.isClass.html +1 -1
  25. package/docs/functions/misc.isEmpty.html +1 -1
  26. package/docs/functions/misc.isError.html +1 -1
  27. package/docs/functions/misc.isThenable.html +1 -1
  28. package/docs/functions/misc.shallowEqual.html +1 -1
  29. package/docs/functions/misc.toBool.html +3 -0
  30. package/docs/functions/run.lazy.html +1 -1
  31. package/docs/functions/run.require.html +1 -1
  32. package/docs/functions/run.runScripts.html +1 -1
  33. package/docs/functions/transition.Transition.html +3 -3
  34. package/docs/index.html +3 -3
  35. package/docs/modules/misc.html +1 -1
  36. package/docs/modules/run.html +1 -1
  37. package/docs/static/demos/error-1.jsx +10 -0
  38. package/docs/static/demos/error-2.jsx +7 -0
  39. package/docs/static/demos/error-3.jsx +9 -0
  40. package/docs/static/demos/form-elements.jsx +110 -0
  41. package/docs/static/index.html +8 -4
  42. package/docs/static/lilact.development.min.js +1 -1
  43. package/docs/static/lilact.production.min.js +1 -1
  44. package/docs/variables/misc.required_scripts.html +1 -0
  45. package/package.json +2 -2
  46. package/root/demos/error-1.jsx +10 -0
  47. package/root/demos/error-2.jsx +7 -0
  48. package/root/demos/error-3.jsx +9 -0
  49. package/root/demos/form-elements.jsx +110 -0
  50. package/root/index.html +8 -4
  51. package/root/lilact.development.min.js +1 -1
  52. package/root/lilact.production.min.js +1 -1
  53. package/src/components.jsx +41 -22
  54. package/src/errors.jsx +217 -0
  55. package/src/events.jsx +4 -14
  56. package/src/jsx.js +35 -43
  57. package/src/lilact.jsx +13 -5
  58. package/src/misc.jsx +44 -73
  59. package/src/run.jsx +22 -96
  60. package/docs/functions/run.traceError.html +0 -6
  61. /package/docs/static/demos/{boundary.jsx → error-boundary.jsx} +0 -0
  62. /package/root/demos/{boundary.jsx → error-boundary.jsx} +0 -0
package/src/errors.jsx ADDED
@@ -0,0 +1,217 @@
1
+ /*
2
+
3
+ Lilact
4
+ Copyright (C) 2024-2026 Arash Kazemi <contact.arash.kazemi@gmail.com>
5
+ All rights reserved.
6
+
7
+ BSD-2-Clause
8
+
9
+ Redistribution and use in source and binary forms, with or without
10
+ modification, are permitted provided that the following conditions are met:
11
+
12
+ * Redistributions of source code must retain the above copyright
13
+ notice, this list of conditions and the following disclaimer.
14
+ * Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in the
16
+ documentation and/or other materials provided with the distribution.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ */
30
+
31
+
32
+
33
+ // Lilact API
34
+ /** @ignore */
35
+ export function getErrorLocation(err) // works for both error and error-event, and also in node env
36
+ {
37
+ if(err.lineno!==undefined || err.line!==undefined || err.lineNumber!==undefined) {
38
+ const l = err.lineno || err.line || err.lineNumber;
39
+ const c = err.colno || err.column || err.columnNumber;
40
+
41
+ return [l, c];
42
+ }
43
+
44
+ let match = /:(\d+):(\d+)[\n].*/m.exec(err.stack);
45
+ if(match===null) {
46
+ match = /:(\d+):(\d+)\)\s+at .*/m.exec(err.stack);
47
+ }
48
+
49
+ if(match) {
50
+ return [parseInt(match[1]), parseInt(match[2])]
51
+ }
52
+
53
+ return null;
54
+ }
55
+
56
+ /** @ignore */
57
+ export function mapLocation(mps, r,c)
58
+ {
59
+ let map = [0,0,0,0];
60
+
61
+ for(const i in mps) {
62
+ if(mps[i][0]<r) continue;
63
+ if(mps[i][0]>r || mps[i][1]>=c) {
64
+ map = mps[i-1];
65
+ break;
66
+ }
67
+ }
68
+
69
+ return [r-map[0]+map[2], ((r-map[0]===0)?map[3]:0)];
70
+ }
71
+
72
+
73
+ /** @ignore */
74
+ export function scanBlockLabels(code, path)
75
+ {
76
+ const ls = Array.from( code.matchAll(/LILACTBLOCK(\d+):(\d+),(\d+):([^*]+)\*\//mg) );
77
+
78
+ ls.forEach(
79
+ (x) => {
80
+ Lilact.blocks_info.labels[x[1]] = {
81
+ path,
82
+ row: parseInt(x[2]),
83
+ col: parseInt(x[3]),
84
+ desc: x[4]
85
+ }
86
+ //console.log(Lilact.blocks_info.labels[x[1]]);
87
+ } );
88
+ }
89
+
90
+
91
+ /**
92
+ * Debug tool to get the Lilact traced location of an error. It can also produce some block based stack trace
93
+ * if `Lilact.transpilerConfig.enableLabelStack` is set to `true` before loading the script. This is `false`
94
+ * by default for efficiency.
95
+ *
96
+ * @returns A new object that includes `path`, `row`, `col`, `msg`, `name`, and optional `stack`.
97
+ * The exception itself is stored as `err`.
98
+ */
99
+ export function traceError(err)
100
+ {
101
+ const loc = Lilact.getErrorLocation(err);
102
+
103
+ const obj = {
104
+ fileName: err.fileName,
105
+ label: null,
106
+
107
+ lineNumber: loc[0],
108
+ columnNumber: loc[1],
109
+
110
+ message: err.message,
111
+ name: err.name,
112
+
113
+ stack: null,
114
+ error: err,
115
+
116
+ is_traced: true
117
+ };
118
+
119
+ if(err.lilact_trace!==undefined) {
120
+
121
+ // to be able to trace, we assume that all of the scripts are running inside lilact.
122
+ // if not, the error is returned unchanged and stack and label would remain null.
123
+
124
+ let mps;
125
+ let blk;
126
+
127
+ if(typeof(err.lilact_trace)==='object') {
128
+ blk = Lilact.blocks_info.labels[err.lilact_trace[0]];
129
+ }
130
+ else {
131
+ blk = Lilact.blocks_info.labels[err.lilact_trace];
132
+ }
133
+
134
+ if(blk) {
135
+ obj.fileName = blk.path;
136
+ obj.label = blk.label;
137
+
138
+ mps = Lilact.required_scripts[blk.path].mappings;
139
+
140
+ [obj.lineNumber, obj.columnNumber] = Lilact.mapLocation(mps, obj.lineNumber,obj.columnNumber);
141
+
142
+ //const rm = Lilact.block_labels[block_num].required;
143
+
144
+ // Lilact.onError( err.message,
145
+ // rm.path,
146
+ // Lilact.block_labels[block_num].label,
147
+ // ...Lilact.mapLocation(...loc,mps),
148
+ // Lilact.call_stack.map(
149
+ // (x)=>({ path: Lilact.block_labels[x].path,
150
+ // label: Lilact.block_labels[x].label,
151
+ // lineNumber: Lilact.block_labels[x].lineNumber
152
+ // })
153
+ // ), err );
154
+ }
155
+
156
+ }
157
+ Lilact.error = obj;
158
+ return obj;
159
+
160
+ }
161
+
162
+ export function globalErrorHandler(err)
163
+ {
164
+ //console.log(err);
165
+ if(err.error) err = err.error;
166
+
167
+ if(!err?.is_traced && err.name!=='JSXParseError') err = Lilact.traceError(err);
168
+ const cls = Lilact.emotion.css(`
169
+ background: linear-gradient(135deg, #fff2f2d4, #ffffffd4);
170
+ backdrop-filter: blur(10px);
171
+ border: 1px solid rgba(255,255,255,.25);
172
+ border-radius: 5px;
173
+ box-shadow: 0 10px 30px rgba(0,0,0,.35);
174
+ overflow:hidden;
175
+ min-width: 400px;
176
+ width: 66%;
177
+ red {
178
+ color:#d00;
179
+ }
180
+ code {
181
+ border: 1px solid #0003;
182
+ overflow: auto;
183
+ }
184
+ `);
185
+
186
+ const el = document.createElement('dialog');
187
+
188
+
189
+ el.className=cls;
190
+ el.innerHTML =
191
+ `<h3 style=""><red>Error!</red></h3>
192
+ At <b>${err.fileName}: Line ${err.lineNumber+1}, Column ${err.columnNumber+1}</b><br><br>
193
+ <b>${err.name}</b>:&nbsp;<span>${err.message}</span><br><br>
194
+ <code><pre></pre><pre><red></red></pre><pre></pre></code>
195
+ `;
196
+ document.body.appendChild(el);
197
+
198
+
199
+ if(Lilact.required_scripts[err.fileName]) {
200
+ const lines = Lilact.required_scripts[err.fileName].code.split("\n");
201
+ if(err.lineNumber>0)
202
+ el.querySelectorAll('pre')[0].innerText = lines[err.lineNumber-1];
203
+
204
+ el.querySelector('pre red').innerText = lines[err.lineNumber];
205
+
206
+ if(err.lineNumber<lines.length-1)
207
+ el.querySelectorAll('pre')[2].innerText = lines[err.lineNumber+1];
208
+ }
209
+
210
+ el.showModal();
211
+ }
212
+
213
+ /** @ignore */
214
+ export const blocks_info = { counter: 0, labels: {} };
215
+
216
+ /** @ignore */
217
+ export let error = null; // this is only to ease debuggin,
package/src/events.jsx CHANGED
@@ -58,7 +58,7 @@ if (typeof Event !== 'undefined' && !Event.prototype.composedPath) {
58
58
  const _pool = [];
59
59
  const MAX_POOL_SIZE = 10;
60
60
 
61
- function createSyntheticEvent(nativeEvent, currentTarget) {
61
+ export function createSyntheticEvent(nativeEvent, currentTarget) {
62
62
  // Reuse object from pool if available
63
63
  const e = _pool.length ? _pool.pop() : {};
64
64
 
@@ -104,7 +104,7 @@ function createSyntheticEvent(nativeEvent, currentTarget) {
104
104
  return e;
105
105
  }
106
106
 
107
- function releaseSyntheticEvent(e) {
107
+ export function releaseSyntheticEvent(e) {
108
108
  if (e && !e.isPersistent) {
109
109
  // Clean up references to avoid leaks
110
110
  e.nativeEvent = null;
@@ -133,7 +133,7 @@ function releaseSyntheticEvent(e) {
133
133
  // Main wrapper factory
134
134
  // fn: function(syntheticEvent) { ... }
135
135
  // opts: { capture: bool, passive: bool, once: bool, stopPropagationOnTrueReturn: bool }
136
- function wrapListener(fn, opts = {}) {
136
+ export function wrapListener(fn, opts = {}) {
137
137
  const { stopPropagationOnTrueReturn = false } = opts;
138
138
 
139
139
  return function handler(nativeEvent) {
@@ -156,20 +156,10 @@ function wrapListener(fn, opts = {}) {
156
156
  }
157
157
 
158
158
  // Convenience: add/remove wrapper-managed listener
159
- function addWrappedEventListener(target, type, fn, options = {}) {
159
+ export function addWrappedEventListener(target, type, fn, options = {}) {
160
160
  const handler = wrapListener(fn, options);
161
161
 
162
162
  target.addEventListener(type, handler, options);
163
163
  // Return a remover
164
164
  return () => target.removeEventListener(type, handler, options);
165
165
  }
166
-
167
- // Export (CommonJS / ES module-friendly)
168
- const EventWrapper = {
169
- wrapListener,
170
- addWrappedEventListener,
171
- createSyntheticEvent, // exported for advanced use
172
- releaseSyntheticEvent
173
- };
174
-
175
- export default EventWrapper;
package/src/jsx.js CHANGED
@@ -54,17 +54,12 @@ import * as jsxAddons from './jsx.addons.js';
54
54
  /** @ignore */
55
55
  export const transpilerConfig = {
56
56
  addons: jsxAddons,
57
- setFunctionLabels: true,
57
+ setBlockLabels: true,
58
58
  enableLabelStack: false,
59
59
  injectLabels: true,
60
60
  // todo: alt+shift+7 on apple abc extended layout is better i think,
61
61
  // but my current editor doesn't support syntax highlighting with it.
62
62
  preprocessorDelimiter: 'ʔ', // alt+shift+. on apple abc extended layout
63
-
64
-
65
- required: {},
66
- func_labels: {},
67
- func_num: Math.floor(Math.random()*10000)
68
63
  }
69
64
 
70
65
 
@@ -163,7 +158,7 @@ function parseComment(code, index, container)
163
158
  index++;
164
159
  }
165
160
 
166
- raiseError(`unterminated comment`, index);
161
+ raiseError(`Unterminated comment`, b.begin);
167
162
  }
168
163
 
169
164
 
@@ -215,7 +210,7 @@ function parseDirective(code, index, container)
215
210
  }
216
211
  }
217
212
 
218
- raiseError('error in preprocessor statement.')
213
+ raiseError('Error in preprocessor statement', index);
219
214
  }
220
215
 
221
216
 
@@ -336,7 +331,7 @@ function parseString(code, index, q, container)
336
331
  return b;
337
332
 
338
333
  case '\n':
339
- if(q!=='\`') raiseError(`unterminated string`, index);
334
+ if(q!=='\`') raiseError(`Unterminated string`, b.begin);
340
335
  break;
341
336
 
342
337
  case '$':
@@ -357,7 +352,7 @@ function parseString(code, index, q, container)
357
352
  index++;
358
353
  }
359
354
 
360
- raiseError(`unterminated string`, index);
355
+ raiseError(`Unterminated string`, b.begin);
361
356
  }
362
357
 
363
358
 
@@ -387,7 +382,7 @@ function parseXMLContent(code, index, container, eols)
387
382
  const tag = code.substring(i,j).trim();
388
383
 
389
384
  if(container.tag!==tag) {
390
- throw `ill-formed xml (close tag) [${container.tag},${tag}] ${j}`;
385
+ raiseError(`Ill-formed xml (not closed properly)`, index);
391
386
  }
392
387
 
393
388
  container.end = j+1;
@@ -623,7 +618,7 @@ function parseParanthesis(code, index, container)
623
618
  break;
624
619
 
625
620
  case '}':
626
- raiseError(`unmatched curly bracket`, index);
621
+ raiseError(`Unmatched curly bracket`, b.begin);
627
622
  break;
628
623
 
629
624
  case ')':
@@ -646,7 +641,7 @@ function parseParanthesis(code, index, container)
646
641
  }
647
642
  }
648
643
 
649
- raiseError(`unterminated paranthesis block (started at ${b.begin})`, index);
644
+ raiseError(`Unterminated paranthesis block`, b.begin);
650
645
  }
651
646
 
652
647
 
@@ -689,7 +684,7 @@ function parseJS(code, index=0, is_block=false, container)
689
684
  break;
690
685
 
691
686
  case ')': // this is only for function detection
692
- raiseError(`unmatched paranthesis ${index} [from ${b.begin}]`, index);
687
+ raiseError(`Unmatched paranthesis`, b.begin);
693
688
  break;
694
689
 
695
690
  case '}':
@@ -699,7 +694,7 @@ function parseJS(code, index=0, is_block=false, container)
699
694
  if(container) container.children.push(b);
700
695
  return b;
701
696
  }
702
- raiseError(`unmatched curly bracket`, index);
697
+ raiseError(`Unmatched curly bracket`, b.begin);
703
698
  break;
704
699
 
705
700
  case '/':
@@ -726,7 +721,7 @@ function parseJS(code, index=0, is_block=false, container)
726
721
  }
727
722
  }
728
723
 
729
- if(is_block) raiseError(`unterminated js block at ${index} (started at ${b.begin})`);
724
+ if(is_block) raiseError(`Unterminated JS block`, b.begin);
730
725
 
731
726
  b.end = index;
732
727
  b.cend = index;
@@ -738,7 +733,7 @@ function parseJS(code, index=0, is_block=false, container)
738
733
  // this is for lilact internal use, it is a workaround for approximating error location
739
734
  // in eval when transpiling and running jsx directly in browser.
740
735
 
741
- function labelFunctions(node, eols)
736
+ function labelFunctions(node, eols, blocks_info)
742
737
  {
743
738
 
744
739
  node.already_labeled = true;
@@ -781,12 +776,12 @@ function labelFunctions(node, eols)
781
776
 
782
777
  if(transpilerConfig.injectTraceLabels && typeof(nxt)==='object' && nxt.type==='js') {
783
778
  const begin = getRowCol(eols, chi); // begin is always the location of function args paranthesis
784
- nxt.children.splice(1,0, `/*LILACTBLOCK${++transpilerConfig.func_num}:${begin}:${label}*/try{`);
779
+ nxt.children.splice(1,0, `/*LILACTBLOCK${++blocks_info.counter}:${begin}:${label}*/try{`);
785
780
  if(transpilerConfig.enableLabelStack) {
786
- nxt.children.splice(nxt.children.length-1, 0, `} catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${transpilerConfig.func_num},e.lilact_trace];throw e}`);
781
+ nxt.children.splice(nxt.children.length-1, 0, `} catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${blocks_info.counter},e.lilact_trace];throw e}`);
787
782
  }
788
783
  else {
789
- nxt.children.splice(nxt.children.length-1, 0, `} catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${transpilerConfig.func_num};throw e}`);
784
+ nxt.children.splice(nxt.children.length-1, 0, `} catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${blocks_info.counter};throw e}`);
790
785
  }
791
786
  chi += 2;
792
787
  }
@@ -806,15 +801,15 @@ function labelFunctions(node, eols)
806
801
  if(transpilerConfig.injectTraceLabels) {
807
802
 
808
803
  nxt.children.splice(1,0,
809
- `/*LILACTBLOCK${++transpilerConfig.func_num}:${begin}:<ARROW>*/try {`);
804
+ `/*LILACTBLOCK${++blocks_info.counter}:${begin}:<ARROW>*/try {`);
810
805
 
811
806
  if(transpilerConfig.enableLabelStack) {
812
807
  nxt.children.splice(nxt.children.length-1, 0,
813
- `} catch(e){if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${transpilerConfig.func_num},e.lilact_trace];throw e}`);
808
+ `} catch(e){if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${blocks_info.counter},e.lilact_trace];throw e}`);
814
809
  }
815
810
  else {
816
811
  nxt.children.splice(nxt.children.length-1, 0,
817
- `} catch(e){if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${transpilerConfig.func_num};throw e}`);
812
+ `} catch(e){if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${blocks_info.counter};throw e}`);
818
813
  }
819
814
 
820
815
  }
@@ -943,17 +938,18 @@ export function transpileJSX( jsx, {
943
938
  factory = "Lilact.createComponent",
944
939
  path = "anonymous",
945
940
  appendSourcemap = true,
946
- mappings = [],
941
+ blocks_info = {
942
+ labels: {},
943
+ counter: 0
944
+ },
945
+ mappings = [],
947
946
  injectTraceLabels = false,
948
947
  discardComments = false
949
948
  } = {} )
950
949
  {
951
950
 
952
- // func_num is shared so consecutive transpilations create new ids each time.
953
- transpilerConfig.func_num ??= 0;
954
951
  transpilerConfig.preprocessorDelimiter ??= 'ʔ'; // alt+shift+. on apple abc extended layout
955
-
956
- transpilerConfig.injectTraceLabels ??= injectTraceLabels; // alt+shift+. on apple abc extended layout
952
+ transpilerConfig.injectTraceLabels ??= injectTraceLabels;
957
953
 
958
954
  const eols = scanEOLs(jsx);
959
955
 
@@ -961,6 +957,7 @@ export function transpileJSX( jsx, {
961
957
  const er = new Error(msg);
962
958
  er.name = 'JSXParseError';
963
959
  [er.lineNumber, er.columnNumber] = getRowCol(eols, index);
960
+ er.fileName = path;
964
961
  er.lilact_trace = 'parse';
965
962
  throw er;
966
963
  }).bind(null, eols);
@@ -1012,7 +1009,11 @@ export function transpileJSX( jsx, {
1012
1009
  if(node.type==='xml') s = s.trim();
1013
1010
  if(s.length) {
1014
1011
  if(node.type==='xml') {
1015
- node.children.push( '"'+s.replaceAll("\n", "\\\n")+'"' );
1012
+ node.children.push( '"'+s.replace(/[\\\"\n]/g, m => ({
1013
+ '\\': '\\\\',
1014
+ '"': '\\"',
1015
+ '\n': '\\\n'
1016
+ }[m]))+'"' );
1016
1017
  }
1017
1018
  else {
1018
1019
  node.children.push( ...s.split(tokenize_re) );
@@ -1022,8 +1023,8 @@ export function transpileJSX( jsx, {
1022
1023
 
1023
1024
  node.children = node.children.filter( (x)=>x!=="" );
1024
1025
 
1025
- if(transpilerConfig.setFunctionLabels && !node.already_labeled) {
1026
- labelFunctions(node,eols);
1026
+ if(transpilerConfig.setBlockLabels && !node.already_labeled) {
1027
+ labelFunctions(node,eols, blocks_info);
1027
1028
  }
1028
1029
  }
1029
1030
  }
@@ -1127,25 +1128,16 @@ export function transpileJSX( jsx, {
1127
1128
 
1128
1129
  let out = '';
1129
1130
  if(injectTraceLabels) {
1130
- out=`/*LILACTBLOCK${++transpilerConfig.func_num}:0,0:<EXEC>*/try{`
1131
-
1132
- transpilerConfig.func_labels[transpilerConfig.func_num] = {
1133
- path,
1134
- row: 1,
1135
- col: 1,
1136
- label: transpilerConfig.func_num,
1137
- required: transpilerConfig.required[path]
1138
- };
1139
-
1131
+ out=`/*LILACTBLOCK${++blocks_info.counter}:0,0:<EXEC>*/try{`
1140
1132
  }
1141
1133
  out+=codify(0, json);
1142
1134
 
1143
1135
  if(injectTraceLabels) {
1144
1136
  if(transpilerConfig.enableLabelStack) {
1145
- out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${transpilerConfig.func_num},e.lilact_trace];throw e}`;
1137
+ out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${blocks_info.counter},e.lilact_trace];throw e}`;
1146
1138
  }
1147
1139
  else {
1148
- out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${transpilerConfig.func_num};throw e}`;
1140
+ out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${blocks_info.counter};throw e}`;
1149
1141
  }
1150
1142
  }
1151
1143
 
package/src/lilact.jsx CHANGED
@@ -39,10 +39,11 @@ import * as components from './components.jsx';
39
39
  import * as hooks from './hooks.jsx';
40
40
  import * as run from './run.jsx';
41
41
  import * as transition from './transition.jsx';
42
- import EventWrapper from './events.jsx';
42
+ import * as events from './events.jsx';
43
43
  import * as redux_wrapper from './redux.jsx';
44
44
  import * as timers from './timers.jsx';
45
45
  import * as misc from './misc.jsx';
46
+ import * as errors from './errors.jsx';
46
47
 
47
48
 
48
49
  import * as router from './router.jsx';
@@ -63,7 +64,7 @@ import {transpileJSX, transpilerConfig} from "./jsx";
63
64
  export const Lilact =
64
65
  {
65
66
 
66
- VERSION: "beta.3",
67
+ VERSION: "beta.5",
67
68
 
68
69
  // Configuration
69
70
 
@@ -73,14 +74,15 @@ export const Lilact =
73
74
 
74
75
  // Units
75
76
 
77
+ ...misc,
78
+ ...run,
76
79
  ...components,
77
80
  ...hooks,
78
- ...run,
79
81
  ...transition,
80
82
  ...redux_wrapper,
81
83
  ...timers,
82
- ...misc,
83
- ...EventWrapper,
84
+ ...events,
85
+ ...errors,
84
86
 
85
87
  ...router,
86
88
  ...accessories,
@@ -97,10 +99,16 @@ export const Lilact =
97
99
 
98
100
  }
99
101
 
102
+ globalThis.Lilact = Lilact;
103
+
100
104
  document.addEventListener('DOMContentLoaded', () => {
101
105
  Lilact.runScripts();
102
106
  });
103
107
 
108
+ window.addEventListener('error', (e) => {
109
+ Lilact.globalErrorHandler(e);
110
+ });
111
+
104
112
  ʔ if(DEBUG) {
105
113
  console.log(`Lilact (Version: ${Lilact.VERSION}) - Debug Mode`);
106
114
  console.log(`Copyright(C) 2024-2026 Arash Kazemi <contact.arash.kazemi@gmail.com>`);