lilact 0.27.0 → 0.27.2

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 (73) hide show
  1. package/dist/lilact.development.js +238 -135
  2. package/dist/lilact.development.js.map +3 -3
  3. package/dist/lilact.development.min.js +57 -57
  4. package/dist/lilact.development.min.js.map +3 -3
  5. package/dist/lilact.production.min.js +57 -57
  6. package/docs/classes/accessories.ErrorBoundary.html +3 -3
  7. package/docs/classes/accessories.Suspense.html +2 -2
  8. package/docs/classes/components.Component.html +3 -3
  9. package/docs/classes/components.HTMLComponent.html +4 -4
  10. package/docs/classes/components.RootComponent.html +5 -5
  11. package/docs/functions/components.cloneComponent.html +1 -1
  12. package/docs/functions/components.createComponent.html +1 -1
  13. package/docs/functions/components.createPortal.html +1 -1
  14. package/docs/functions/components.createRoot.html +1 -1
  15. package/docs/functions/components.memo.html +1 -1
  16. package/docs/functions/components.render.html +1 -1
  17. package/docs/functions/hooks.createContext.html +1 -1
  18. package/docs/functions/hooks.startTransition.html +1 -1
  19. package/docs/functions/hooks.useActionState.html +1 -1
  20. package/docs/functions/hooks.useContext.html +1 -1
  21. package/docs/functions/hooks.useDebugValue.html +1 -1
  22. package/docs/functions/hooks.useDeferredValue.html +1 -1
  23. package/docs/functions/hooks.useEffect.html +1 -1
  24. package/docs/functions/hooks.useId.html +1 -1
  25. package/docs/functions/hooks.useImperativeHandle.html +1 -1
  26. package/docs/functions/hooks.useInsertionEffect.html +1 -1
  27. package/docs/functions/hooks.useLayoutEffect.html +1 -1
  28. package/docs/functions/hooks.useLocalStorage.html +1 -1
  29. package/docs/functions/hooks.useMemo.html +1 -1
  30. package/docs/functions/hooks.useReducer.html +1 -1
  31. package/docs/functions/hooks.useRef.html +1 -1
  32. package/docs/functions/hooks.useTransition.html +1 -1
  33. package/docs/functions/misc.Fragment.html +2 -2
  34. package/docs/functions/misc.Portal.html +2 -2
  35. package/docs/functions/misc.deepEqual.html +1 -1
  36. package/docs/functions/misc.findDOMNode.html +1 -1
  37. package/docs/functions/misc.forwardRef.html +1 -1
  38. package/docs/functions/misc.getComponentByPointer.html +1 -1
  39. package/docs/functions/misc.isAsync.html +1 -1
  40. package/docs/functions/misc.isClass.html +1 -1
  41. package/docs/functions/misc.isEmpty.html +1 -1
  42. package/docs/functions/misc.isError.html +1 -1
  43. package/docs/functions/misc.isThenable.html +1 -1
  44. package/docs/functions/misc.shallowEqual.html +1 -1
  45. package/docs/functions/misc.toBool.html +1 -1
  46. package/docs/functions/run.lazy.html +1 -1
  47. package/docs/functions/run.require.html +1 -1
  48. package/docs/functions/run.run.html +1 -1
  49. package/docs/functions/run.runScripts.html +1 -1
  50. package/docs/functions/timers.timeoutPromise.html +10 -10
  51. package/docs/static/index.html +1 -1
  52. package/docs/static/lilact.development.js +238 -135
  53. package/docs/static/lilact.development.js.map +3 -3
  54. package/docs/static/lilact.development.min.js +57 -57
  55. package/docs/static/lilact.development.min.js.map +3 -3
  56. package/docs/static/lilact.production.min.js +57 -57
  57. package/docs/variables/components.cloneElement.html +1 -1
  58. package/docs/variables/misc.Children.html +10 -10
  59. package/docs/variables/misc.isValidElement.html +1 -1
  60. package/docs/variables/run.required_scripts.html +1 -1
  61. package/examples/index.html +1 -1
  62. package/examples/lilact.development.js +238 -135
  63. package/examples/lilact.development.js.map +3 -3
  64. package/examples/lilact.development.min.js +57 -57
  65. package/examples/lilact.development.min.js.map +3 -3
  66. package/examples/lilact.production.min.js +57 -57
  67. package/package.json +1 -1
  68. package/src/components.jsx +24 -13
  69. package/src/errors.jsx +310 -310
  70. package/src/hooks.jsx +60 -44
  71. package/src/lilact.jsx +4 -2
  72. package/src/misc.jsx +46 -18
  73. package/src/run.jsx +406 -291
package/src/errors.jsx CHANGED
@@ -38,365 +38,365 @@ import { required_scripts } from "./run.jsx";
38
38
  import { css } from "@emotion/css";
39
39
 
40
40
  function number(value) {
41
- const result = Number(value);
42
- return Number.isFinite(result) ? result : null;
41
+ const result = Number(value);
42
+ return Number.isFinite(result) ? result : null;
43
43
  }
44
44
 
45
45
  function asError(value) {
46
- if (value instanceof Error) return value;
47
- if (value?.error instanceof Error) return value.error;
46
+ if (value instanceof Error) return value;
47
+ if (value?.error instanceof Error) return value.error;
48
48
 
49
- const error = new Error(
50
- value?.message == null
51
- ? String(value)
52
- : String(value.message)
53
- );
49
+ const error = new Error(
50
+ value?.message == null
51
+ ? String(value)
52
+ : String(value.message)
53
+ );
54
54
 
55
- if (value && typeof value === "object") {
56
- if (value.name) error.name = value.name;
57
- if (value.stack) error.stack = value.stack;
55
+ if (value && typeof value === "object") {
56
+ if (value.name) error.name = value.name;
57
+ if (value.stack) error.stack = value.stack;
58
58
 
59
- for (const key of Object.keys(value)) {
60
- if (!(key in error)) error[key] = value[key];
61
- }
62
- }
59
+ for (const key of Object.keys(value)) {
60
+ if (!(key in error)) error[key] = value[key];
61
+ }
62
+ }
63
63
 
64
- return error;
64
+ return error;
65
65
  }
66
66
 
67
67
  function isParserError(error) {
68
- return error?.name === "JSXParserError";
68
+ return error?.name === "JSXParserError";
69
69
  }
70
70
 
71
71
  function stackLocation(stack) {
72
- if (typeof stack !== "string") return null;
72
+ if (typeof stack !== "string") return null;
73
73
 
74
- for (const line of stack.split(/\r?\n/)) {
75
- const match = line.match(/(eval:\/.*):(\d+):(\d+)/);
74
+ for (const line of stack.split(/\r?\n/)) {
75
+ const match = line.match(/(eval:\/.*):(\d+):(\d+)/);
76
76
 
77
- if (!match) continue;
77
+ if (!match) continue;
78
78
 
79
- return {
80
- path: match[1].replace(/^eval:\/+/, ""),
81
- line: Number(match[2]) - 1,
82
- column: Number(match[3]) - 1,
83
- };
84
- }
79
+ return {
80
+ path: match[1].replace(/^eval:\/+/, ""),
81
+ line: Number(match[2]) - 1,
82
+ column: Number(match[3]) - 1,
83
+ };
84
+ }
85
85
 
86
- return null;
86
+ return null;
87
87
  }
88
88
 
89
89
  function browserLocation(error) {
90
- const line = number(
91
- error?.lineNumber ??
92
- error?.lineno ??
93
- error?.line
94
- );
95
-
96
- const column = number(
97
- error?.columnNumber ??
98
- error?.colno ??
99
- error?.column
100
- );
101
-
102
- return {
103
- line: line == null ? null : Math.max(0, line - 1),
104
- column: column == null ? null : Math.max(0, column - 1),
105
- };
90
+ const line = number(
91
+ error?.lineNumber ??
92
+ error?.lineno ??
93
+ error?.line
94
+ );
95
+
96
+ const column = number(
97
+ error?.columnNumber ??
98
+ error?.colno ??
99
+ error?.column
100
+ );
101
+
102
+ return {
103
+ line: line == null ? null : Math.max(0, line - 1),
104
+ column: column == null ? null : Math.max(0, column - 1),
105
+ };
106
106
  }
107
107
 
108
108
  function traceBlock(error) {
109
- const trace = error?.lilact_trace;
110
- return Array.isArray(trace) ? trace[0] : trace;
109
+ const trace = error?.lilact_trace;
110
+ return Array.isArray(trace) ? trace[0] : trace;
111
111
  }
112
112
 
113
113
  function blockInfo(error) {
114
- const trace = traceBlock(error);
115
- return trace == null
116
- ? null
117
- : Lilact.blocks_info?.labels?.[trace];
114
+ const trace = traceBlock(error);
115
+ return trace == null
116
+ ? null
117
+ : Lilact.blocks_info?.labels?.[trace];
118
118
  }
119
119
 
120
120
  function mapLocation(mappings, line, column) {
121
- if (
122
- !Array.isArray(mappings) ||
123
- !mappings.length ||
124
- !Number.isFinite(line) ||
125
- !Number.isFinite(column)
126
- ) {
127
- return { line, column };
128
- }
129
-
130
- const valid = mappings
131
- .filter(mapping =>
132
- Array.isArray(mapping) &&
133
- mapping.length >= 4 &&
134
- mapping
135
- .slice(0, 4)
136
- .every(value => Number.isFinite(Number(value)))
137
- )
138
- .sort((a, b) =>
139
- Number(a[0]) - Number(b[0]) ||
140
- Number(a[1]) - Number(b[1])
141
- );
142
-
143
- if (!valid.length) return { line, column };
144
-
145
- let selected = valid[0];
146
-
147
- for (const mapping of valid) {
148
- const generatedLine = Number(mapping[0]);
149
- const generatedColumn = Number(mapping[1]);
150
-
151
- if (
152
- generatedLine < line ||
153
- (
154
- generatedLine === line &&
155
- generatedColumn <= column
156
- )
157
- ) {
158
- selected = mapping;
159
- } else {
160
- break;
161
- }
162
- }
163
-
164
- const generatedLine = Number(selected[0]);
165
- const generatedColumn = Number(selected[1]);
166
- const sourceLine = Number(selected[2]);
167
- const sourceColumn = Number(selected[3]);
168
-
169
- return {
170
- line:
171
- sourceLine +
172
- (line === generatedLine ? 0 : line - generatedLine),
173
- column:
174
- line === generatedLine
175
- ? Math.max(0, sourceColumn + column - generatedColumn)
176
- : sourceColumn,
177
- };
121
+ if (
122
+ !Array.isArray(mappings) ||
123
+ !mappings.length ||
124
+ !Number.isFinite(line) ||
125
+ !Number.isFinite(column)
126
+ ) {
127
+ return { line, column };
128
+ }
129
+
130
+ const valid = mappings
131
+ .filter(mapping =>
132
+ Array.isArray(mapping) &&
133
+ mapping.length >= 4 &&
134
+ mapping
135
+ .slice(0, 4)
136
+ .every(value => Number.isFinite(Number(value)))
137
+ )
138
+ .sort((a, b) =>
139
+ Number(a[0]) - Number(b[0]) ||
140
+ Number(a[1]) - Number(b[1])
141
+ );
142
+
143
+ if (!valid.length) return { line, column };
144
+
145
+ let selected = valid[0];
146
+
147
+ for (const mapping of valid) {
148
+ const generatedLine = Number(mapping[0]);
149
+ const generatedColumn = Number(mapping[1]);
150
+
151
+ if (
152
+ generatedLine < line ||
153
+ (
154
+ generatedLine === line &&
155
+ generatedColumn <= column
156
+ )
157
+ ) {
158
+ selected = mapping;
159
+ } else {
160
+ break;
161
+ }
162
+ }
163
+
164
+ const generatedLine = Number(selected[0]);
165
+ const generatedColumn = Number(selected[1]);
166
+ const sourceLine = Number(selected[2]);
167
+ const sourceColumn = Number(selected[3]);
168
+
169
+ return {
170
+ line:
171
+ sourceLine +
172
+ (line === generatedLine ? 0 : line - generatedLine),
173
+ column:
174
+ line === generatedLine
175
+ ? Math.max(0, sourceColumn + column - generatedColumn)
176
+ : sourceColumn,
177
+ };
178
178
  }
179
179
 
180
180
  export function traceError(value, runPath) {
181
- if (value?.isTraced) return value;
182
-
183
- const error = asError(value);
184
- const source = error.lilact_source;
185
- const stack = isParserError(error)
186
- ? null
187
- : stackLocation(error.stack);
188
- const browser = isParserError(error)
189
- ? {
190
- line: number(error.lineNumber),
191
- column: number(error.columnNumber),
192
- }
193
- : browserLocation(error);
194
-
195
- /*
196
- * lilact_source is authoritative. In particular, it prevents a syntax
197
- * error from a nested eval from inheriting the caller's eval filename.
198
- */
199
- const fileName =
200
- source?.path ||
201
- stack?.path ||
202
- error.fileName ||
203
- runPath ||
204
- null;
205
-
206
- let line =
207
- stack?.line ??
208
- browser.line ??
209
- null;
210
-
211
- let column =
212
- stack?.column ??
213
- browser.column ??
214
- null;
215
-
216
- const result = {
217
- fileName,
218
- lineNumber: line,
219
- columnNumber: column,
220
- message:
221
- error.message == null
222
- ? String(error)
223
- : String(error.message),
224
- name: error.name || "Error",
225
- stack: error.stack || null,
226
- lilact_source: source || null,
227
- _error: error,
228
- isTraced: true,
229
- };
230
-
231
- const module = fileName && required_scripts[fileName];
232
-
233
- if (module) {
234
- const mapped = mapLocation(
235
- module.mappings,
236
- result.lineNumber,
237
- result.columnNumber
238
- );
239
-
240
- result.lineNumber = mapped.line;
241
- result.columnNumber = mapped.column;
242
- }
243
-
244
- const block = blockInfo(error);
245
-
246
- if (
247
- block &&
248
- (
249
- result.lineNumber == null ||
250
- result.columnNumber == null ||
251
- !result.fileName
252
- )
253
- ) {
254
- result.fileName ||= block.path || runPath || null;
255
- result.lineNumber ??= block.line;
256
- result.columnNumber ??= block.col;
257
- result.label = block.desc;
258
- }
259
-
260
- Lilact.error = result;
261
- return result;
181
+ if (value?.isTraced) return value;
182
+
183
+ const error = asError(value);
184
+ const source = error.lilact_source;
185
+ const stack = isParserError(error)
186
+ ? null
187
+ : stackLocation(error.stack);
188
+ const browser = isParserError(error)
189
+ ? {
190
+ line: number(error.lineNumber),
191
+ column: number(error.columnNumber),
192
+ }
193
+ : browserLocation(error);
194
+
195
+ /*
196
+ * lilact_source is authoritative. In particular, it prevents a syntax
197
+ * error from a nested eval from inheriting the caller's eval filename.
198
+ */
199
+ const fileName =
200
+ source?.path ||
201
+ stack?.path ||
202
+ error.fileName ||
203
+ runPath ||
204
+ null;
205
+
206
+ let line =
207
+ stack?.line ??
208
+ browser.line ??
209
+ null;
210
+
211
+ let column =
212
+ stack?.column ??
213
+ browser.column ??
214
+ null;
215
+
216
+ const result = {
217
+ fileName,
218
+ lineNumber: line,
219
+ columnNumber: column,
220
+ message:
221
+ error.message == null
222
+ ? String(error)
223
+ : String(error.message),
224
+ name: error.name || "Error",
225
+ stack: error.stack || null,
226
+ lilact_source: source || null,
227
+ _error: error,
228
+ isTraced: true,
229
+ };
230
+
231
+ const module = fileName && required_scripts[fileName];
232
+
233
+ if (module) {
234
+ const mapped = mapLocation(
235
+ module.mappings,
236
+ result.lineNumber,
237
+ result.columnNumber
238
+ );
239
+
240
+ result.lineNumber = mapped.line;
241
+ result.columnNumber = mapped.column;
242
+ }
243
+
244
+ const block = blockInfo(error);
245
+
246
+ if (
247
+ block &&
248
+ (
249
+ result.lineNumber == null ||
250
+ result.columnNumber == null ||
251
+ !result.fileName
252
+ )
253
+ ) {
254
+ result.fileName ||= block.path || runPath || null;
255
+ result.lineNumber ??= block.line;
256
+ result.columnNumber ??= block.col;
257
+ result.label = block.desc;
258
+ }
259
+
260
+ Lilact.error = result;
261
+ return result;
262
262
  }
263
263
 
264
264
  function escapeHtml(value) {
265
- return String(value ?? "")
266
- .replaceAll("&", "&amp;")
267
- .replaceAll("<", "&lt;")
268
- .replaceAll(">", "&gt;")
269
- .replaceAll('"', "&quot;")
270
- .replaceAll("'", "&#39;");
265
+ return String(value ?? "")
266
+ .replaceAll("&", "&amp;")
267
+ .replaceAll("<", "&lt;")
268
+ .replaceAll(">", "&gt;")
269
+ .replaceAll('"', "&quot;")
270
+ .replaceAll("'", "&#39;");
271
271
  }
272
272
 
273
273
  function sourceExcerpt(module, line) {
274
- if (!module || !Number.isFinite(line)) return null;
274
+ if (!module || !Number.isFinite(line)) return null;
275
275
 
276
- const lines = String(module.code ?? "").split(/\r?\n/);
276
+ const lines = String(module.code ?? "").split(/\r?\n/);
277
277
 
278
- return {
279
- before: lines[line - 1] ?? "",
280
- current: lines[line] ?? "",
281
- after: lines[line + 1] ?? "",
282
- };
278
+ return {
279
+ before: lines[line - 1] ?? "",
280
+ current: lines[line] ?? "",
281
+ after: lines[line + 1] ?? "",
282
+ };
283
283
  }
284
284
 
285
285
  export function globalErrorHandler(eventOrError) {
286
- const value =
287
- eventOrError?.error instanceof Error
288
- ? eventOrError.error
289
- : eventOrError?.reason !== undefined
290
- ? eventOrError.reason
291
- : eventOrError;
292
-
293
- const error = traceError(
294
- value,
295
- eventOrError?.fileName || null
296
- );
297
-
298
- const excerpt = sourceExcerpt(
299
- required_scripts[error.fileName],
300
- error.lineNumber
301
- );
302
-
303
- const className = css(`
304
- background: linear-gradient(135deg, #fff2f2d4, #ffffffd4);
305
- backdrop-filter: blur(10px);
306
- border: 1px solid rgba(255,255,255,.25);
307
- border-radius: 5px;
308
- box-shadow: 0 10px 30px rgba(0,0,0,.35);
309
- overflow: hidden;
310
- min-width: 400px;
311
- width: 66%;
312
-
313
- red {
314
- color: #d00;
315
- }
316
-
317
- code {
318
- border: 1px solid #0003;
319
- overflow: auto;
320
- padding: 10px;
321
- display: block;
322
- }
323
- `);
324
-
325
- const dialog = document.createElement("dialog");
326
- dialog.className = className;
327
-
328
- const location = error.fileName
329
- ? `At ${escapeHtml(error.fileName)}`
330
- : "";
331
-
332
- const line = Number.isFinite(error.lineNumber)
333
- ? `: Line ${error.lineNumber + 1}`
334
- : "";
335
-
336
- const componentStack =
337
- error._error?.componentStackLog ||
338
- error._error?.componentStack ||
339
- "";
340
-
341
- dialog.innerHTML = `
342
- <h3><red>Error!</red></h3>
343
- <b>${location}${line}</b><br><br>
344
- <b>${escapeHtml(error.name)}</b>:
345
- <span>${escapeHtml(error.message)}</span>
346
- <br><br>
347
-
348
- ${
349
- excerpt
350
- ? "<code><pre></pre><red><pre></pre></red><pre></pre></code>"
351
- : ""
352
- }
353
-
354
- ${
355
- componentStack
356
- ? `
357
- <br>
358
- Component Stack:
359
- <br>
360
- <code><pre>${escapeHtml(componentStack)}</pre></code>
361
- `
362
- : ""
363
- }
364
- `;
365
-
366
- if (excerpt) {
367
- const pre = dialog.querySelectorAll("pre");
368
- pre[0].innerText = excerpt.before;
369
- pre[1].innerText = excerpt.current;
370
- pre[2].innerText = excerpt.after;
371
- }
372
-
373
- document.body.appendChild(dialog);
374
-
375
- if (typeof dialog.showModal === "function") {
376
- dialog.showModal();
377
- } else {
378
- dialog.setAttribute("open", "");
379
- }
380
-
381
- return error;
286
+ const value =
287
+ eventOrError?.error instanceof Error
288
+ ? eventOrError.error
289
+ : eventOrError?.reason !== undefined
290
+ ? eventOrError.reason
291
+ : eventOrError;
292
+
293
+ const error = traceError(
294
+ value,
295
+ eventOrError?.fileName || null
296
+ );
297
+
298
+ const excerpt = sourceExcerpt(
299
+ required_scripts[error.fileName],
300
+ error.lineNumber
301
+ );
302
+
303
+ const className = css(`
304
+ background: linear-gradient(135deg, #fff2f2d4, #ffffffd4);
305
+ backdrop-filter: blur(10px);
306
+ border: 1px solid rgba(255,255,255,.25);
307
+ border-radius: 5px;
308
+ box-shadow: 0 10px 30px rgba(0,0,0,.35);
309
+ overflow: hidden;
310
+ min-width: 400px;
311
+ width: 66%;
312
+
313
+ red {
314
+ color: #d00;
315
+ }
316
+
317
+ code {
318
+ border: 1px solid #0003;
319
+ overflow: auto;
320
+ padding: 10px;
321
+ display: block;
322
+ }
323
+ `);
324
+
325
+ const dialog = document.createElement("dialog");
326
+ dialog.className = className;
327
+
328
+ const location = error.fileName
329
+ ? `At ${escapeHtml(error.fileName)}`
330
+ : "";
331
+
332
+ const line = Number.isFinite(error.lineNumber)
333
+ ? `: Line ${error.lineNumber + 1}`
334
+ : "";
335
+
336
+ const componentStack =
337
+ error._error?.componentStackLog ||
338
+ error._error?.componentStack ||
339
+ "";
340
+
341
+ dialog.innerHTML = `
342
+ <h3><red>Error!</red></h3>
343
+ <b>${location}${line}</b><br><br>
344
+ <b>${escapeHtml(error.name)}</b>:
345
+ <span>${escapeHtml(error.message)}</span>
346
+ <br><br>
347
+
348
+ ${
349
+ excerpt
350
+ ? "<code><pre></pre><red><pre></pre></red><pre></pre></code>"
351
+ : ""
352
+ }
353
+
354
+ ${
355
+ componentStack
356
+ ? `
357
+ <br>
358
+ Component Stack:
359
+ <br>
360
+ <code><pre>${escapeHtml(componentStack)}</pre></code>
361
+ `
362
+ : ""
363
+ }
364
+ `;
365
+
366
+ if (excerpt) {
367
+ const pre = dialog.querySelectorAll("pre");
368
+ pre[0].innerText = excerpt.before;
369
+ pre[1].innerText = excerpt.current;
370
+ pre[2].innerText = excerpt.after;
371
+ }
372
+
373
+ document.body.appendChild(dialog);
374
+
375
+ if (typeof dialog.showModal === "function") {
376
+ dialog.showModal();
377
+ } else {
378
+ dialog.setAttribute("open", "");
379
+ }
380
+
381
+ return error;
382
382
  }
383
383
 
384
384
  export function scanBlockLabels(code, path) {
385
- for (const match of String(code).matchAll(
386
- /LILACTBLOCK(\d+):(\d+),(\d+):([^*]+)\*\//gm
387
- )) {
388
- Lilact.blocks_info.labels[match[1]] = {
389
- path,
390
- line: Number(match[2]),
391
- col: Number(match[3]),
392
- desc: match[4],
393
- };
394
- }
385
+ for (const match of String(code).matchAll(
386
+ /LILACTBLOCK(\d+):(\d+),(\d+):([^*]+)\*\//gm
387
+ )) {
388
+ Lilact.blocks_info.labels[match[1]] = {
389
+ path,
390
+ line: Number(match[2]),
391
+ col: Number(match[3]),
392
+ desc: match[4],
393
+ };
394
+ }
395
395
  }
396
396
 
397
397
  export const blocks_info = {
398
- counter: 0,
399
- labels: {},
398
+ counter: 0,
399
+ labels: {},
400
400
  };
401
401
 
402
402
  export let error = null;