lilact 0.29.2 → 0.29.3

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 (35) hide show
  1. package/dist/lilact.development.js +106 -71
  2. package/dist/lilact.development.js.map +3 -3
  3. package/dist/lilact.development.min.js +23 -23
  4. package/dist/lilact.development.min.js.map +3 -3
  5. package/dist/lilact.production.min.js +23 -23
  6. package/docs/classes/accessories.ErrorBoundary.html +8 -8
  7. package/docs/classes/accessories.Suspense.html +7 -7
  8. package/docs/classes/components.Component.html +11 -11
  9. package/docs/classes/components.HTMLComponent.html +11 -11
  10. package/docs/classes/components.RootComponent.html +11 -11
  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/run.lazy.html +1 -1
  18. package/docs/functions/run.run.html +1 -1
  19. package/docs/functions/run.runScripts.html +1 -1
  20. package/docs/static/index.html +1 -1
  21. package/docs/static/lilact.development.js +106 -71
  22. package/docs/static/lilact.development.js.map +3 -3
  23. package/docs/static/lilact.development.min.js +23 -23
  24. package/docs/static/lilact.development.min.js.map +3 -3
  25. package/docs/static/lilact.production.min.js +23 -23
  26. package/docs/variables/components.cloneElement.html +1 -1
  27. package/examples/index.html +1 -1
  28. package/examples/lilact.development.js +106 -71
  29. package/examples/lilact.development.js.map +3 -3
  30. package/examples/lilact.development.min.js +23 -23
  31. package/examples/lilact.development.min.js.map +3 -3
  32. package/examples/lilact.production.min.js +23 -23
  33. package/package.json +1 -1
  34. package/src/components.jsx +108 -44
  35. package/src/run.jsx +41 -46
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lilact",
3
- "version": "0.29.2",
3
+ "version": "0.29.3",
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/",
@@ -37,6 +37,50 @@ import { PropTypes } from './proptypes.jsx';
37
37
 
38
38
  const SVG_NS = "http://www.w3.org/2000/svg";
39
39
 
40
+
41
+ function getComponentEntity(entity) {
42
+ return entity?.[MEMOIZED]
43
+ ? entity.component
44
+ : entity;
45
+ }
46
+
47
+ function replaceComponentEntity(comp, nextEntity) {
48
+ const core = comp?.[CORE];
49
+
50
+ if (!core || typeof nextEntity !== "function") {
51
+ return;
52
+ }
53
+
54
+ const oldEntity = getComponentEntity(core.entity);
55
+ const newEntity = getComponentEntity(nextEntity);
56
+
57
+ if (oldEntity === newEntity) {
58
+ return;
59
+ }
60
+
61
+ const oldIsClass = isClass(oldEntity);
62
+ const newIsClass = isClass(newEntity);
63
+
64
+ // A function component and a class component have different instance
65
+ // semantics. Let the cache create a fresh instance in that case.
66
+ if (oldIsClass !== newIsClass) {
67
+ return false;
68
+ }
69
+
70
+ if (newIsClass) {
71
+ // Preserve the existing instance and state, but use the new class
72
+ // prototype and therefore the new render/lifecycle methods.
73
+ Object.setPrototypeOf(comp, newEntity.prototype);
74
+ } else {
75
+ // Preserve hooks and state, but replace the function implementation.
76
+ comp.render = newEntity.bind(comp);
77
+ }
78
+
79
+ core.entity = newEntity;
80
+ return true;
81
+ }
82
+
83
+
40
84
  /*
41
85
  ComponentCache is for internal use. It is the heart of the JSX runtime,
42
86
  it holds child components and detects which one is being rendered or updated.
@@ -54,39 +98,46 @@ class ComponentCache
54
98
  this.owner = owner;
55
99
  }
56
100
 
57
- pick(key, construct_func)
58
- {
101
+ pick(key, construct_func, nextEntity) {
59
102
  let comp;
60
- let buck = this.current_map.get(key);
61
-
62
- if(buck && buck.length>buck[IDX]) {
63
- comp = buck[buck[IDX]];
64
- buck[IDX]++;
65
-
66
- buck = this.new_map.get(key);
67
- if(buck!==undefined) {
68
- buck.push( comp );
69
- }
70
- else {
71
- buck = [ comp ];
72
- this.new_map.set(key, buck);
73
- buck[IDX]=0;
103
+ let bucket = this.current_map.get(key);
104
+ const reusable =
105
+ bucket && bucket.length > bucket[IDX];
106
+
107
+ if (reusable) {
108
+ comp = bucket[bucket[IDX]];
109
+ bucket[IDX]++;
110
+
111
+ const oldEntity = getComponentEntity(comp?.[CORE]?.entity);
112
+ const newEntity = getComponentEntity(nextEntity);
113
+
114
+ const incompatible =
115
+ typeof oldEntity === "function" &&
116
+ typeof newEntity === "function" &&
117
+ isClass(oldEntity) !== isClass(newEntity);
118
+
119
+ if (incompatible) {
120
+ // Do not reuse a class instance as a function component or vice versa.
121
+ comp = construct_func();
122
+ } else {
123
+ replaceComponentEntity(comp, nextEntity);
74
124
  }
75
- }
76
- else {
125
+ } else {
77
126
  comp = construct_func();
127
+ }
78
128
 
79
- buck = this.new_map.get(key);
80
- if(buck!==undefined) {
81
- buck.push( comp );
82
- }
83
- else {
84
- buck = [ comp ];
85
- this.new_map.set(key, buck);
86
- buck[IDX]=0;
87
- }
129
+ bucket = this.new_map.get(key);
130
+
131
+ if (bucket !== undefined) {
132
+ bucket.push(comp);
133
+ } else {
134
+ bucket = [comp];
135
+ this.new_map.set(key, bucket);
136
+ bucket[IDX] = 0;
137
+ }
88
138
 
89
- if(comp[CORE]) comp[CORE].parent ??= this.owner;
139
+ if (comp[CORE]) {
140
+ comp[CORE].parent ??= this.owner;
90
141
  }
91
142
 
92
143
  return comp;
@@ -757,22 +808,35 @@ function constructFunc(core, parent) // returns {text} or component, and not com
757
808
  }
758
809
 
759
810
 
760
- function prepareCore(parent, core)
761
- {
762
- try {
763
- parent.cache ??= new ComponentCache(parent);
764
- core = parent.cache.pick( core[TEXT]===undefined?core?.props?.key:':text:',
765
- ()=>( (core[TEXT]!==undefined || core instanceof ComponentCore) ?
766
- core : constructFunc(core, parent)[CORE] )
767
- );
768
- return core;
769
- }
770
- catch(e) {
771
- if(core?.component?.componentDidCatch) {
772
- core.component.componentDidCatch(e);
773
- }
774
- else throw(e);
775
- }
811
+ function prepareCore(parent, core) {
812
+ try {
813
+ parent.cache ??= new ComponentCache(parent);
814
+
815
+ const isText = core[TEXT] !== undefined;
816
+ const key = isText
817
+ ? ':text:'
818
+ : core.props?.key;
819
+
820
+ const entity = isText || core instanceof ComponentCore
821
+ ? undefined
822
+ : core.entity;
823
+
824
+ return parent.cache.pick(
825
+ key,
826
+ () => (
827
+ isText || core instanceof ComponentCore
828
+ ? core
829
+ : constructFunc(core, parent)[CORE]
830
+ ),
831
+ entity
832
+ );
833
+ } catch (e) {
834
+ if (core?.component?.componentDidCatch) {
835
+ core.component.componentDidCatch(e);
836
+ } else {
837
+ throw e;
838
+ }
839
+ }
776
840
  }
777
841
 
778
842
 
package/src/run.jsx CHANGED
@@ -172,11 +172,11 @@ function loadModule(path, options = {}) {
172
172
  if (loadAsync) {
173
173
  Lilact[LAZY] = false;
174
174
 
175
- if (module.request) {
176
- return module.request;
177
- }
175
+ if (module.request && !options.forceReload) {
176
+ return module.request;
177
+ }
178
178
 
179
- return loadAsyncResource(path, module);
179
+ return loadAsyncResource(path, module, options);
180
180
  }
181
181
 
182
182
  const resolved = Lilact.resolver?.(path);
@@ -244,58 +244,52 @@ export function require(path)
244
244
  }
245
245
 
246
246
 
247
- function makeImportsObject(mod)
248
- {
249
- mod.importsObject = {};
247
+ function makeImportsObject(mod, options = {}) {
248
+ mod.importsObject = {};
250
249
 
251
- for (const path in mod.meta.imports) {
252
- const imps = mod.meta.imports[path];
250
+ for (const path in mod.meta.imports) {
251
+ const imps = mod.meta.imports[path];
253
252
 
254
- /*
255
- * Do not use require() here. loadModule() resolves and loads the
256
- * dependency, then evaluates it directly through run().
257
- */
258
- const exps = loadModule(path, {
259
- requirer: mod,
260
- });
253
+ const exps = loadModule(path, {
254
+ requirer: mod,
255
+ forceReload: options.forceReload,
256
+ });
261
257
 
262
- for (const i in imps.named_imports) {
263
- if (i === '') continue;
258
+ for (const i in imps.named_imports) {
259
+ if (i === '') continue;
264
260
 
265
- const exportedName = imps.named_imports[i];
261
+ const exportedName = imps.named_imports[i];
266
262
 
267
- if (!Object.prototype.hasOwnProperty.call(exps, exportedName)) {
268
- throw new Error(
269
- `Imported module does not export any "${i}".`
270
- );
271
- }
263
+ if (!Object.prototype.hasOwnProperty.call(exps, exportedName)) {
264
+ throw new Error(
265
+ `Imported module does not export any "${i}".`
266
+ );
267
+ }
272
268
 
273
- mod.importsObject[i] = exps[exportedName];
274
- }
269
+ mod.importsObject[i] = exps[exportedName];
270
+ }
275
271
 
276
- for (const i of imps.import_defaults) {
277
- if (!Object.prototype.hasOwnProperty.call(exps, 'default')) {
278
- throw new Error(
279
- `Imported module does not export a default.`
280
- );
281
- }
272
+ for (const i of imps.import_defaults) {
273
+ if (!Object.prototype.hasOwnProperty.call(exps, 'default')) {
274
+ throw new Error(
275
+ `Imported module does not export a default.`
276
+ );
277
+ }
282
278
 
283
- mod.importsObject[i] = exps.default;
284
- }
279
+ mod.importsObject[i] = exps.default;
280
+ }
285
281
 
286
- for (const i of imps.import_stars) {
287
- mod.importsObject[i] = {...exps};
288
- }
289
- }
282
+ for (const i of imps.import_stars) {
283
+ mod.importsObject[i] = { ...exps };
284
+ }
285
+ }
290
286
  }
291
287
 
292
- // ERROR IS FOUND WHEN run IS CALLED, AND NOT REQUIRE.
293
- // REQUIRE REWRITES MODULE ANYWAY. THAT IS ALSO A PROBLEM.
294
288
 
295
289
  export function run(
296
- jsx,
297
- path = `InlineJSX-${++Lilact.eval_num}`,
298
- {} = {}
290
+ jsx,
291
+ path = `InlineJSX-${++Lilact.eval_num}`,
292
+ options = {}
299
293
  ) {
300
294
  let module = required_scripts[path];
301
295
 
@@ -363,7 +357,7 @@ export function run(
363
357
  globalThis.createComponent = Lilact.createComponent;
364
358
  globalThis.Fragment = Lilact.Fragment;
365
359
 
366
- makeImportsObject(module);
360
+ makeImportsObject(module, options);
367
361
 
368
362
  Lilact.scriptImportsObject = module.importsObject;
369
363
  const result = eval(processed);
@@ -383,7 +377,8 @@ function getOrCreateModule(path, options = {}) {
383
377
  return required_scripts[path] || createModule(path, options);
384
378
  }
385
379
 
386
- function loadAsyncResource(path, module) {
380
+ function loadAsyncResource(path, module, options = {})
381
+ {
387
382
  let source;
388
383
 
389
384
  try {
@@ -429,7 +424,7 @@ function loadAsyncResource(path, module) {
429
424
  return undefined;
430
425
  }
431
426
 
432
- return run(module.code, path, {});
427
+ return run(module.code, path, options);
433
428
  })
434
429
  .then(result => result?.default ?? result)
435
430
  .catch(error => {