lilact 0.28.4 → 0.29.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 (45) hide show
  1. package/dist/lilact.development.js +227 -179
  2. package/dist/lilact.development.js.map +3 -3
  3. package/dist/lilact.development.min.js +29 -29
  4. package/dist/lilact.development.min.js.map +3 -3
  5. package/dist/lilact.production.min.js +29 -29
  6. package/docs/assets/navigation.js +1 -1
  7. package/docs/assets/search.js +1 -1
  8. package/docs/classes/accessories.ErrorBoundary.html +8 -8
  9. package/docs/classes/accessories.Suspense.html +7 -7
  10. package/docs/classes/components.Component.html +11 -11
  11. package/docs/classes/components.HTMLComponent.html +11 -11
  12. package/docs/classes/components.RootComponent.html +11 -11
  13. package/docs/functions/components.cloneComponent.html +1 -1
  14. package/docs/functions/components.createComponent.html +1 -1
  15. package/docs/functions/components.createPortal.html +1 -1
  16. package/docs/functions/components.createRoot.html +1 -1
  17. package/docs/functions/components.memo.html +1 -1
  18. package/docs/functions/components.render.html +1 -1
  19. package/docs/functions/errors.asError.html +1 -0
  20. package/docs/functions/run.lazy.html +1 -1
  21. package/docs/functions/run.require.html +1 -1
  22. package/docs/functions/run.run.html +1 -1
  23. package/docs/functions/run.runScripts.html +1 -1
  24. package/docs/modules/errors.html +1 -1
  25. package/docs/static/index.html +3 -6
  26. package/docs/static/lilact.development.js +227 -179
  27. package/docs/static/lilact.development.js.map +3 -3
  28. package/docs/static/lilact.development.min.js +29 -29
  29. package/docs/static/lilact.development.min.js.map +3 -3
  30. package/docs/static/lilact.production.min.js +29 -29
  31. package/docs/variables/components.cloneElement.html +1 -1
  32. package/docs/variables/errors.blocksInfo.html +1 -0
  33. package/examples/index.html +3 -4
  34. package/examples/lilact.development.js +227 -179
  35. package/examples/lilact.development.js.map +3 -3
  36. package/examples/lilact.development.min.js +29 -29
  37. package/examples/lilact.development.min.js.map +3 -3
  38. package/examples/lilact.production.min.js +29 -29
  39. package/package.json +1 -1
  40. package/src/components.jsx +118 -122
  41. package/src/errors.jsx +4 -4
  42. package/src/expscan.js +40 -15
  43. package/src/jsx.js +67 -38
  44. package/src/run.jsx +51 -39
  45. package/docs/variables/errors.blocks_info.html +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lilact",
3
- "version": "0.28.4",
3
+ "version": "0.29.0",
4
4
  "description": "A Little React/JSX Runtime Implementation for Browser",
5
5
  "repository": "github:arashkazemi/lilact",
6
6
  "homepage": "https://arashkazemi.github.io/lilact/",
@@ -169,177 +169,173 @@ class ComponentCore
169
169
  // TODO: should componentDidUpdate be called after arranging/appending the outlet or before?
170
170
  apply(next_props = this.props, next_state = this.next_state || this.state)
171
171
  {
172
+ try {
172
173
 
173
- let do_rerender = true;
174
+ let do_rerender = true;
174
175
 
175
- if(this.outlet && this?.[MEMOIZED]) {
176
+ if(this.outlet && this?.[MEMOIZED]) {
176
177
 
177
- if( shallowEqual(this.props, next_props, "children") &&
178
- shallowEqual(this.props?.children, next_props?.children) ) {
179
- do_rerender=false;
178
+ if( shallowEqual(this.props, next_props, "children") &&
179
+ shallowEqual(this.props?.children, next_props?.children) ) {
180
+ do_rerender=false;
181
+ }
180
182
  }
181
- }
182
183
 
183
- if(do_rerender) {
184
+ if(do_rerender) {
184
185
 
185
- if(DEBUG) {
186
+ if(DEBUG) {
186
187
 
187
- if(this.entity?.propTypes) {
188
- PropTypes.checkPropTypes(this.entity.propTypes, this.props, 'prop', this.entity.name);
189
- }
190
- else if(this.component?.propTypes) {
191
- PropTypes.checkPropTypes(this.component.propTypes, this.props, 'prop', this.component.name);
192
- }
188
+ if(this.entity?.propTypes) {
189
+ PropTypes.checkPropTypes(this.entity.propTypes, this.props, 'prop', this.entity.name);
190
+ }
191
+ else if(this.component?.propTypes) {
192
+ PropTypes.checkPropTypes(this.component.propTypes, this.props, 'prop', this.component.name);
193
+ }
193
194
 
194
- }
195
- if(typeof(next_state)==='function') next_state = next_state(this.state);
195
+ }
196
+ if(typeof(next_state)==='function') next_state = next_state(this.state);
196
197
 
197
- if(this.component.constructor.defaultProps) {
198
- next_props = {...this.component.constructor.defaultProps, ...next_props};
199
- }
198
+ if(this.component.constructor.defaultProps) {
199
+ next_props = {...this.component.constructor.defaultProps, ...next_props};
200
+ }
200
201
 
201
- if(this?.parent?.component?.context || this?.parent?.component?.getChildContext ) {
202
- this.context = { ...this.parent.component.context, ...this.parent.component.getChildContext?.() };
202
+ if(this?.parent?.component?.context || this?.parent?.component?.getChildContext ) {
203
+ this.context = { ...this.parent.component.context, ...this.parent.component.getChildContext?.() };
203
204
 
204
- if(DEBUG && this.component.constructor.contextTypes) {
205
- PropTypes.checkPropTypes(this.component.constructor.contextTypes, this.context, 'context', this.entity.name);
205
+ if(DEBUG && this.component.constructor.contextTypes) {
206
+ PropTypes.checkPropTypes(this.component.constructor.contextTypes, this.context, 'context', this.entity.name);
207
+ }
206
208
  }
207
- }
208
209
 
209
- if( this.component.shouldComponentUpdate &&
210
- !this.component.shouldComponentUpdate
211
- (next_state, next_props, this.context) ) return;
210
+ if( this.component.shouldComponentUpdate &&
211
+ !this.component.shouldComponentUpdate
212
+ (next_state, next_props, this.context) ) return;
212
213
 
213
214
 
214
- if( typeof(this.entity)==='string' ) {
215
- if(!(this.element instanceof Element)) {
215
+ if( typeof(this.entity)==='string' ) {
216
+ if(!(this.element instanceof Element)) {
216
217
 
217
- if(this.is_svg || this.container.is_svg) {
218
- this.is_svg = true;
219
- this.element = document.createElementNS(SVG_NS, this.entity);
218
+ if(this.is_svg || this.container.is_svg) {
219
+ this.is_svg = true;
220
+ this.element = document.createElementNS(SVG_NS, this.entity);
221
+ }
222
+ else {
223
+ this.element = document.createElement(this.entity);
224
+ }
225
+ if(next_props?.defaultValue) this.element.value = String(next_props.defaultValue).slice(0, next_props?.maxLength);
226
+ if(next_props?.defaultChecked) this.element.checked = next_props.defaultChecked;
227
+ }
228
+ this.element[COMPONENT] = this.component;
229
+ }
230
+
231
+ if(next_props.ref) {
232
+ if(typeof(next_props.ref)==='function') {
233
+ next_props.ref(this.element || this.component);
220
234
  }
221
235
  else {
222
- this.element = document.createElement(this.entity);
236
+ next_props.ref.current = this.element || this.component;
223
237
  }
224
- if(next_props?.defaultValue) this.element.value = String(next_props.defaultValue).slice(0, next_props?.maxLength);
225
- if(next_props?.defaultChecked) this.element.checked = next_props.defaultChecked;
226
238
  }
227
- this.element[COMPONENT] = this.component;
228
- }
229
239
 
230
- if(next_props.ref) {
231
- if(typeof(next_props.ref)==='function') {
232
- next_props.ref(this.element || this.component);
233
- }
234
- else {
235
- next_props.ref.current = this.element || this.component;
240
+ if(next_props!==undefined && this.component.componentWillReceiveProps) {
241
+ this.component.componentWillReceiveProps(next_props);
236
242
  }
237
- }
238
-
239
- if(next_props!==undefined && this.component.componentWillReceiveProps) {
240
- this.component.componentWillReceiveProps(next_props);
241
- }
242
243
 
243
- if(this.component.componentWillUpdate) {
244
- this.component.componentWillUpdate(next_props, next_state);
245
- }
244
+ if(this.component.componentWillUpdate) {
245
+ this.component.componentWillUpdate(next_props, next_state);
246
+ }
246
247
 
247
- const prev_state = this.state, prev_props=this.props;
248
+ const prev_state = this.state, prev_props=this.props;
248
249
 
249
- if(this.element) {
250
- this.updateElementProps(next_props);
251
- }
252
- this.props = next_props;
250
+ if(this.element) {
251
+ this.updateElementProps(next_props);
252
+ }
253
+ this.props = next_props;
253
254
 
254
- if(typeof this.next_state==='object') {
255
- if(!this.state) this.state = {...next_state};
256
- else Object.assign( this.state, next_state );
257
- }
258
- else if(this.next_state!==undefined) throw new Error('Component.setState only accepts objects or functions is new state.');
255
+ if(typeof this.next_state==='object') {
256
+ if(!this.state) this.state = {...next_state};
257
+ else Object.assign( this.state, next_state );
258
+ }
259
+ else if(this.next_state!==undefined) throw new Error('Component.setState only accepts objects or functions is new state.');
259
260
 
260
261
 
261
- if(this.next_state) delete this.next_state;
262
+ if(this.next_state) delete this.next_state;
262
263
 
263
264
 
264
- if(this.hooks!==undefined) {
265
- this.hook_index = 0;
266
- Lilact.current_component = [this, Lilact.current_component];
265
+ if(this.hooks!==undefined) {
266
+ this.hook_index = 0;
267
+ Lilact.current_component = [this, Lilact.current_component];
267
268
 
268
- try {
269
269
  this.outlet = this.component.render(next_props, {current: this.element || this.component} );
270
- }
271
- catch(e) {
272
- renderErrorHandler(this, e);
273
- }
274
270
 
275
- Lilact.current_component = Lilact.current_component[1];
276
- }
277
- else {
278
- try {
279
- this.outlet = this.component.render({current: this.element || this.component});
271
+ Lilact.current_component = Lilact.current_component[1];
280
272
  }
281
- catch(e) {
282
- renderErrorHandler(this, e);
273
+ else {
274
+ this.outlet = this.component.render({current: this.element || this.component});
283
275
  }
284
- }
285
276
 
286
- if( this?.portal ) {
287
- this.element = this.portal;
288
- }
289
-
290
- if(this.outlet?.constructor?.name!=='Array') {
291
- this.outlet = [this.outlet];
292
- }
293
-
294
- this.outlet = [...this.outlet];
295
-
296
- for (let i=0;i<this.outlet.length;i++) {
297
- let item = this.outlet[i];
298
-
299
- if(item===undefined || item===null || typeof(item)==='boolean') {
300
- this.outlet.splice(i, 1);
301
- i--;
277
+ if( this?.portal ) {
278
+ this.element = this.portal;
302
279
  }
303
- else if(typeof item==='function') {
304
- const res = this.childFunctionHandler(item);
305
- this.outlet.splice(i, 1, res);
306
- i--;
307
- }
308
- else if(item.constructor.name === 'Array') {
309
- this.outlet.splice(i, 1, ...item);
310
- i--;
280
+
281
+ if(this.outlet?.constructor?.name!=='Array') {
282
+ this.outlet = [this.outlet];
311
283
  }
312
284
  else {
313
- const core = prepareCore(this, item);
314
- this.outlet[i] = core;
285
+ this.outlet = [...this.outlet];
286
+ }
287
+
288
+ for (let i=0;i<this.outlet.length;i++) {
289
+ let item = this.outlet[i];
315
290
 
316
- if(core[TEXT]===undefined) {
317
- core.container= this.element? this : this.container;
318
- core.apply(item.props);
291
+ if(item===undefined || item===null || typeof(item)==='boolean') {
292
+ this.outlet.splice(i, 1);
293
+ i--;
294
+ }
295
+ else if(typeof item==='function') {
296
+ const res = this.childFunctionHandler(item);
297
+ this.outlet.splice(i, 1, res);
298
+ i--;
299
+ }
300
+ else if(item.constructor.name === 'Array') {
301
+ this.outlet.splice(i, 1, ...item);
302
+ i--;
319
303
  }
320
304
  else {
321
- if(!core.element) {
322
- core.element = document.createTextNode(item[TEXT]);
323
- core[TEXT] = item[TEXT];
305
+ const core = prepareCore(this, item);
306
+ this.outlet[i] = core;
307
+
308
+ if(core[TEXT]===undefined) {
309
+ core.container = this.element? this : this.container;
310
+ core.apply(item.props);
324
311
  }
325
- else if(core[TEXT]!==item[TEXT]) {
326
- core.element.textContent = item[TEXT];
327
- core[TEXT] = item[TEXT];
312
+ else {
313
+ if(!core.element) {
314
+ core.element = document.createTextNode(item[TEXT]);
315
+ core[TEXT] = item[TEXT];
316
+ }
317
+ else if(core[TEXT]!==item[TEXT]) {
318
+ core.element.textContent = item[TEXT];
319
+ core[TEXT] = item[TEXT];
320
+ }
328
321
  }
329
322
  }
330
323
  }
331
- }
332
324
 
333
- if(this.cache) this.cache.commit();
325
+ if(this.cache) this.cache.commit();
334
326
 
327
+ if(this.element) this.arrangeOutlet();
335
328
 
336
- if(this.element) this.arrangeOutlet();
329
+ if(this.component.componentDidUpdate) {
330
+ this.component.componentDidUpdate(prev_props, prev_state, this.last_snapshot);
331
+ }
337
332
 
338
- if(this.component.componentDidUpdate) {
339
- this.component.componentDidUpdate(prev_props, prev_state, this.last_snapshot);
333
+ if(this.last_snapshot) delete this.last_snapshot;
340
334
  }
341
335
 
342
- if(this.last_snapshot) delete this.last_snapshot;
336
+ }
337
+ catch(e) {
338
+ renderErrorHandler(this, e);
343
339
  }
344
340
 
345
341
  }
@@ -604,7 +600,7 @@ if(DEBUG) {
604
600
  core.container.appendElement(core);
605
601
  }
606
602
  else {
607
- if(core.arrangeOutlet) core.arrangeOutlet();
603
+ if(core.arrangeOutlet && core.outlet) core.arrangeOutlet();
608
604
 
609
605
  // todo: is there a way to remove this useless flag?
610
606
  if(!core?.mounted) {
@@ -618,7 +614,6 @@ if(DEBUG) {
618
614
  }
619
615
  }
620
616
  }
621
-
622
617
  }
623
618
 
624
619
  // note: override this to tailor function children like <Transition>{(state)=>{...}}</Transition>
@@ -633,10 +628,12 @@ if(DEBUG) {
633
628
  const renderErrorHandler = (c, e) =>
634
629
  {
635
630
  const stack = [c];
631
+
636
632
  while(c && !c.component?.componentDidCatch) {
637
633
  c = c.parent;
638
634
  if(c) stack.push(c);
639
635
  }
636
+
640
637
  if(c?.component?.componentDidCatch) {
641
638
  if(c.entity?.getDerivedStateFromError) {
642
639
  c.component.setState(c.entity.getDerivedStateFromError.call(c, e));
@@ -655,7 +652,6 @@ const renderErrorHandler = (c, e) =>
655
652
  c.component.componentDidCatch(e, {componentStack: stack, componentStackLog: stack_log});
656
653
  }
657
654
  else throw(e);
658
-
659
655
  }
660
656
 
661
657
 
package/src/errors.jsx CHANGED
@@ -51,7 +51,7 @@ function number(value) {
51
51
  return Number.isFinite(result) ? result : null;
52
52
  }
53
53
 
54
- function asError(value) {
54
+ export function asError(value) {
55
55
  if (value instanceof Error) return value;
56
56
  if (value?.error instanceof Error) return value.error;
57
57
 
@@ -130,7 +130,7 @@ function blockInfo(error) {
130
130
  const trace = traceBlock(error);
131
131
  return trace == null
132
132
  ? null
133
- : Lilact.blocks_info?.labels?.[trace];
133
+ : Lilact.blocksInfo?.labels?.[trace];
134
134
  }
135
135
 
136
136
  function mapLocation(mappings, line, column) {
@@ -408,7 +408,7 @@ export function scanBlockLabels(code, path) {
408
408
  for (const match of String(code).matchAll(
409
409
  /LILACTBLOCK(\d+):(\d+),(\d+):([^*]+)\*\//gm
410
410
  )) {
411
- Lilact.blocks_info.labels[match[1]] = {
411
+ Lilact.blocksInfo.labels[match[1]] = {
412
412
  path,
413
413
  line: Number(match[2]),
414
414
  column: Number(match[3]),
@@ -417,7 +417,7 @@ export function scanBlockLabels(code, path) {
417
417
  }
418
418
  }
419
419
 
420
- export const blocks_info = {
420
+ export const blocksInfo = {
421
421
  counter: 0,
422
422
  labels: {},
423
423
  };
package/src/expscan.js CHANGED
@@ -106,7 +106,7 @@ export function generateSequence(arr, labeler = labeler.bind(null, null))
106
106
  const import_export_regexp = /(?:i[C \n]*(?:(?:I|J|(?:\*[C \n]*a[C \n]*I))[C \n]*,[C \n]*)*(?:(?:(?:I(?:[C \n]*a[C \n]*I)?)|J|(?:\*[C \n]*a[C \n]*I))[C \n]*f[C \n]*)?S)|(?:e[C \n]*(?:(?:[*J][C \n]*f[C \n]*S)|(?:d[C \n]*[IFJ])|J|(?:[VF][c \n]*I)|I))|(?:r[c \n]*P)/mg;
107
107
  const props_regexp = /O[C \n]*(?:[Id](?:[C \n]*a[C \n]*I)?[C \n]*,[C \n]*)*(?:I(?:[C \n]*a[C \n]*I)?)[C \n]*O/mg;
108
108
 
109
- export function processImportExports(node, jsx)
109
+ export function processImportExports(node, jsx, meta)
110
110
  {
111
111
  const s = generateSequence(node.out,
112
112
  labeler.bind(null,
@@ -150,6 +150,10 @@ export function processImportExports(node, jsx)
150
150
 
151
151
  begins.push(node.end);
152
152
 
153
+ meta.imports ??= {};
154
+
155
+ const imported_names = new Set;
156
+
153
157
  for (const m of s.matchAll(import_export_regexp)) {
154
158
 
155
159
  // Require (to inject requirer argument)
@@ -173,9 +177,10 @@ export function processImportExports(node, jsx)
173
177
  if(s[i]==='.') continue;
174
178
 
175
179
  const src = jsx.substring(node.out[m.index+imp.length-1].begin, node.out[m.index+imp.length-1].end);
176
- const imports = {};
177
- let star_imports = [];
178
- let import_alls = [];
180
+ const named_imports = {};
181
+ let import_stars = [];
182
+ let import_defaults = [];
183
+
179
184
 
180
185
  for(i = m.index+1;i<m.index+imp.length-1;i++) {
181
186
 
@@ -192,7 +197,7 @@ export function processImportExports(node, jsx)
192
197
  case ',':
193
198
  break;
194
199
  case 'I': {
195
- import_alls.push(node.out[i]);
200
+ import_defaults.push(node.out[i]);
196
201
  continue;
197
202
  }
198
203
  case 'J': {
@@ -214,11 +219,11 @@ export function processImportExports(node, jsx)
214
219
  if(sj[j]==='a') {
215
220
  j++;
216
221
  while(sj[j]===' ' || sj[j]==='\n' || sj[j]==='C') j++;
217
- imports[ps[j]] = prop;
222
+ named_imports[ps[j]] = prop;
218
223
  j++;
219
224
  }
220
225
  else {
221
- imports[prop] = prop;
226
+ named_imports[prop] = prop;
222
227
  }
223
228
  }
224
229
  continue;
@@ -230,7 +235,7 @@ export function processImportExports(node, jsx)
230
235
  i++;
231
236
  skip_spaces();
232
237
 
233
- star_imports.push(node.out[i]);
238
+ import_stars.push(node.out[i]);
234
239
  continue;
235
240
  }
236
241
  case 'S':
@@ -240,28 +245,31 @@ export function processImportExports(node, jsx)
240
245
  }
241
246
 
242
247
  let cjs = '';
243
- for(const s of star_imports) {
248
+ for(const s of import_stars) {
244
249
  cjs+=`const ${s} = require(${src},{requirer:module});\n`;
250
+ imported_names.add(s);
245
251
  }
246
- for(const s of import_alls) {
252
+ for(const s of import_defaults) {
247
253
  cjs+=`const ${s} = require(${src},{requirer:module, checkExport: ['default']}).default;\n`;
254
+ imported_names.add(s);
248
255
  }
249
- if(Object.keys(imports).length) {
256
+ if(Object.keys(named_imports).length) {
250
257
  let o = '{';
251
258
  let ls = '[';
252
259
 
253
- for(const p in imports) {
260
+ for(const p in named_imports) {
261
+ imported_names.add(p);
254
262
  if(o.length>1) {
255
263
  o+=',';
256
264
  ls+=',';
257
265
  }
258
- if(p===imports[p]) {
266
+ if(p===named_imports[p]) {
259
267
  o+=p;
260
268
  ls+=`'${p}'`;
261
269
  }
262
270
  else {
263
- o+=p+":"+imports[p];
264
- ls+=`'${imports[p]}'`;
271
+ o+=p+":"+named_imports[p];
272
+ ls+=`'${named_imports[p]}'`;
265
273
  }
266
274
 
267
275
  }
@@ -272,6 +280,7 @@ export function processImportExports(node, jsx)
272
280
  }
273
281
  else if(cjs.length===0) {
274
282
  cjs+=`require(${src},{requirer:module})`;
283
+ named_imports[''] = src;
275
284
  }
276
285
 
277
286
  // 2. add nodes
@@ -279,6 +288,15 @@ export function processImportExports(node, jsx)
279
288
  continue;
280
289
  }
281
290
  }
291
+
292
+ const ss = src.slice(1,src.length-1);
293
+ if(meta.imports[ss]) {
294
+ meta.imports[ss] = { import_stars: [ ...meta.imports[ss].import_stars, ...import_stars],
295
+ import_defaults: [ ...meta.imports[ss].import_defaults, ...import_defaults],
296
+ named_imports: { ...meta.imports[ss].named_imports, ...named_imports } }
297
+ }
298
+ else meta.imports[ss] = {import_stars, import_defaults, named_imports };
299
+
282
300
  }
283
301
  // Export
284
302
  else {
@@ -418,4 +436,11 @@ export function processImportExports(node, jsx)
418
436
  }
419
437
  }
420
438
  }
439
+
440
+ if(meta.imported_names) {
441
+ meta.imported_names = new Set([...meta.imported_names,...imported_names]);
442
+ }
443
+ else {
444
+ meta.imported_names = imported_names;
445
+ }
421
446
  }