lilact 0.4.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.
- package/README.md +1 -1
- package/bin/transpile-dir.js +2 -2
- package/bin/transpile.js +5 -5
- package/dist/lilact.development.min.js +1 -1
- package/dist/lilact.development.min.js.LICENSE.txt +1 -1
- package/dist/lilact.development.min.js.map +1 -1
- package/dist/lilact.production.min.js +1 -1
- package/dist/lilact.production.min.js.map +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/accessories.ErrorBoundary.html +8 -8
- package/docs/classes/accessories.Suspense.html +7 -7
- package/docs/classes/components.Component.html +10 -10
- package/docs/classes/components.HTMLComponent.html +10 -10
- package/docs/classes/components.RootComponent.html +10 -10
- package/docs/functions/components.createComponent.html +1 -1
- package/docs/functions/components.createRoot.html +1 -1
- package/docs/functions/components.render.html +1 -1
- package/docs/functions/jsx.transpileJSX.html +3 -3
- package/docs/functions/misc.classNames.html +1 -1
- package/docs/functions/misc.deepEqual.html +1 -1
- package/docs/functions/misc.getComponentByPointer.html +1 -1
- package/docs/functions/misc.isAsync.html +1 -1
- package/docs/functions/misc.isClass.html +1 -1
- package/docs/functions/misc.isEmpty.html +1 -1
- package/docs/functions/misc.isError.html +1 -1
- package/docs/functions/misc.isThenable.html +1 -1
- package/docs/functions/misc.shallowEqual.html +1 -1
- package/docs/functions/misc.toBool.html +1 -1
- package/docs/functions/run.lazy.html +1 -1
- package/docs/functions/run.require.html +1 -1
- package/docs/functions/run.runScripts.html +1 -1
- package/docs/functions/transition.Transition.html +3 -3
- package/docs/index.html +1 -1
- package/docs/modules/misc.html +1 -1
- package/docs/modules/run.html +1 -1
- package/docs/static/demos/error-1.jsx +10 -0
- package/docs/static/demos/error-2.jsx +7 -0
- package/docs/static/demos/error-3.jsx +9 -0
- package/docs/static/index.html +7 -4
- package/docs/static/lilact.development.min.js +1 -1
- package/docs/static/lilact.production.min.js +1 -1
- package/docs/variables/misc.required_scripts.html +1 -0
- package/package.json +1 -1
- package/root/demos/error-1.jsx +10 -0
- package/root/demos/error-2.jsx +7 -0
- package/root/demos/error-3.jsx +9 -0
- package/root/index.html +7 -4
- package/root/lilact.development.min.js +1 -1
- package/root/lilact.production.min.js +1 -1
- package/src/components.jsx +14 -12
- package/src/errors.jsx +217 -0
- package/src/events.jsx +4 -14
- package/src/jsx.js +30 -42
- package/src/lilact.jsx +13 -5
- package/src/misc.jsx +2 -59
- package/src/run.jsx +22 -96
- package/docs/functions/run.traceError.html +0 -6
- /package/docs/static/demos/{boundary.jsx → error-boundary.jsx} +0 -0
- /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>: <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
|
-
|
|
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(`
|
|
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('
|
|
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(`
|
|
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(`
|
|
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
|
-
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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${++
|
|
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=[${
|
|
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=${
|
|
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${++
|
|
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=[${
|
|
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=${
|
|
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
|
-
|
|
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);
|
|
@@ -1026,8 +1023,8 @@ export function transpileJSX( jsx, {
|
|
|
1026
1023
|
|
|
1027
1024
|
node.children = node.children.filter( (x)=>x!=="" );
|
|
1028
1025
|
|
|
1029
|
-
if(transpilerConfig.
|
|
1030
|
-
labelFunctions(node,eols);
|
|
1026
|
+
if(transpilerConfig.setBlockLabels && !node.already_labeled) {
|
|
1027
|
+
labelFunctions(node,eols, blocks_info);
|
|
1031
1028
|
}
|
|
1032
1029
|
}
|
|
1033
1030
|
}
|
|
@@ -1131,25 +1128,16 @@ export function transpileJSX( jsx, {
|
|
|
1131
1128
|
|
|
1132
1129
|
let out = '';
|
|
1133
1130
|
if(injectTraceLabels) {
|
|
1134
|
-
out=`/*LILACTBLOCK${++
|
|
1135
|
-
|
|
1136
|
-
transpilerConfig.func_labels[transpilerConfig.func_num] = {
|
|
1137
|
-
path,
|
|
1138
|
-
row: 1,
|
|
1139
|
-
col: 1,
|
|
1140
|
-
label: transpilerConfig.func_num,
|
|
1141
|
-
required: transpilerConfig.required[path]
|
|
1142
|
-
};
|
|
1143
|
-
|
|
1131
|
+
out=`/*LILACTBLOCK${++blocks_info.counter}:0,0:<EXEC>*/try{`
|
|
1144
1132
|
}
|
|
1145
1133
|
out+=codify(0, json);
|
|
1146
1134
|
|
|
1147
1135
|
if(injectTraceLabels) {
|
|
1148
1136
|
if(transpilerConfig.enableLabelStack) {
|
|
1149
|
-
out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${
|
|
1137
|
+
out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=[${blocks_info.counter},e.lilact_trace];throw e}`;
|
|
1150
1138
|
}
|
|
1151
1139
|
else {
|
|
1152
|
-
out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${
|
|
1140
|
+
out += `}catch(e){ if(typeof(e)!=='object') e=new Error(e);e.lilact_trace=${blocks_info.counter};throw e}`;
|
|
1153
1141
|
}
|
|
1154
1142
|
}
|
|
1155
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
|
|
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.
|
|
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
|
-
...
|
|
83
|
-
...
|
|
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>`);
|
package/src/misc.jsx
CHANGED
|
@@ -146,63 +146,6 @@ export const Children = {
|
|
|
146
146
|
};
|
|
147
147
|
|
|
148
148
|
|
|
149
|
-
// Lilact API
|
|
150
|
-
/** @ignore */
|
|
151
|
-
export function getErrorLocation(err) // works for both error and error-event, and also in node env
|
|
152
|
-
{
|
|
153
|
-
if(err.lineno!==undefined || err.line!==undefined || err.lineNumber!==undefined) {
|
|
154
|
-
const l = err.lineno || err.line || err.lineNumber;
|
|
155
|
-
const c = err.colno || err.column || err.columnNumber;
|
|
156
|
-
|
|
157
|
-
return [l, c];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
let match = /:(\d+):(\d+)[\n].*/m.exec(err.stack);
|
|
161
|
-
if(match===null) {
|
|
162
|
-
match = /:(\d+):(\d+)\)\s+at .*/m.exec(err.stack);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if(match) {
|
|
166
|
-
return [parseInt(match[1]), parseInt(match[2])]
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** @ignore */
|
|
173
|
-
export function mapLocation(mps, r,c)
|
|
174
|
-
{
|
|
175
|
-
let map = [0,0,0,0];
|
|
176
|
-
|
|
177
|
-
for(const i in mps) {
|
|
178
|
-
if(mps[i][0]<r) continue;
|
|
179
|
-
if(mps[i][0]>r || mps[i][1]>=c) {
|
|
180
|
-
map = mps[i-1];
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return [r-map[0]+map[2], ((r-map[0]===0)?map[3]:0)];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
/** @ignore */
|
|
190
|
-
export function scanFunctionLabels(code, path)
|
|
191
|
-
{
|
|
192
|
-
const ls = Array.from( code.matchAll(/LILACTBLOCK(\d+):(\d+),(\d+):([^*]+)\*\//mg) );
|
|
193
|
-
|
|
194
|
-
ls.forEach(
|
|
195
|
-
(x) => Lilact.transpilerConfig.func_labels[x[1]] = {
|
|
196
|
-
path,
|
|
197
|
-
row: parseInt(x[2])+1,
|
|
198
|
-
col: parseInt(x[3])+1,
|
|
199
|
-
label: x[4],
|
|
200
|
-
required: Lilact.transpilerConfig.required[path]
|
|
201
|
-
} );
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
149
|
/**
|
|
207
150
|
* Debug tool to detect the component visible at a point on screen.
|
|
208
151
|
*
|
|
@@ -393,6 +336,8 @@ export function toBool(x) {
|
|
|
393
336
|
|
|
394
337
|
// Internals
|
|
395
338
|
|
|
339
|
+
export const required_scripts = {};
|
|
340
|
+
|
|
396
341
|
/** @ignore */
|
|
397
342
|
export let update_timeout = undefined;
|
|
398
343
|
/** @ignore */
|
|
@@ -413,8 +358,6 @@ export let update_cbs = new Set;
|
|
|
413
358
|
/** @ignore */
|
|
414
359
|
export let roots = new Set;
|
|
415
360
|
/** @ignore */
|
|
416
|
-
export let err = null; // this is only to ease debuggin,
|
|
417
|
-
/** @ignore */
|
|
418
361
|
export let layout_effects = new Set;
|
|
419
362
|
|
|
420
363
|
/** @ignore */
|