malinajs 0.7.0-a5 → 0.7.0-a8

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 (3) hide show
  1. package/malina.js +164 -80
  2. package/package.json +1 -1
  3. package/runtime.js +34 -21
package/malina.js CHANGED
@@ -179,22 +179,24 @@
179
179
  };
180
180
 
181
181
 
182
- const replaceElementKeyword = (exp, fn) => {
182
+ const replaceKeyword = (exp, fn) => {
183
183
  let changed = false;
184
184
  let r = parseJS(exp).transform((n, pk) => {
185
185
  if(n.type != 'Identifier') return;
186
186
  if(pk == 'property' || pk == 'params') return;
187
- if(n.name != '$element') return;
188
- n.name = fn();
189
- changed = true;
187
+ let name = fn(n.name);
188
+ if(name) {
189
+ n.name = name;
190
+ changed = true;
191
+ }
190
192
  });
191
- return changed ? r.build().trim() : exp;
193
+ return changed ? r.build() : exp;
192
194
  };
193
195
 
194
196
 
195
197
  const parseJS = (exp) => {
196
198
  let self = {};
197
- self.ast = acorn.parse(exp, { sourceType: 'module', ecmaVersion: 12 });
199
+ self.ast = acorn.parseExpressionAt(exp, 0, {ecmaVersion: 12});
198
200
 
199
201
  self.transform = function(fn) {
200
202
  const rec = (n, pk) => {
@@ -225,7 +227,7 @@
225
227
  };
226
228
 
227
229
  self.build = function(data) {
228
- return astring.generate(data || self.ast);
230
+ return astring.generate(data || self.ast, {indent: '', lineEnd: ''});
229
231
  };
230
232
  return self;
231
233
  };
@@ -1277,7 +1279,6 @@
1277
1279
  let source = this.scriptNodes.length ? this.scriptNodes[0].content : null;
1278
1280
  this.script = {
1279
1281
  source,
1280
- watchers: [],
1281
1282
  imports: [],
1282
1283
  importedNames: [],
1283
1284
  autosubscribeNames: [],
@@ -1429,7 +1430,7 @@
1429
1430
  function walk(node, parent, fn) {
1430
1431
  if(typeof node !== 'object') return;
1431
1432
 
1432
- if(node._apply) return;
1433
+ if(node._apply && node.type == 'ExpressionStatement') return;
1433
1434
  node._parent = parent;
1434
1435
  let forParent = parent;
1435
1436
  if(node.type) {
@@ -1467,6 +1468,8 @@
1467
1468
  };
1468
1469
  }
1469
1470
 
1471
+ let watchers = xNode('block');
1472
+
1470
1473
  const makeWatch = (n) => {
1471
1474
  function assertExpression(n) {
1472
1475
  if(['Identifier', 'TemplateLiteral', 'Literal'].includes(n.type)) return;
@@ -1483,15 +1486,22 @@
1483
1486
  target = ex.left.name;
1484
1487
  if(!(target in rootVariables)) resultBody.push(makeVariable(target));
1485
1488
  } else if(ex.left.type == 'MemberExpression') {
1486
- target = source.substring(ex.left.start, ex.left.end);
1489
+ target = astring.generate(ex.left);
1487
1490
  } else throw 'Error';
1488
1491
  assertExpression(ex.right);
1489
- const exp = source.substring(ex.right.start, ex.right.end);
1490
- result.watchers.push(`$runtime.prefixPush(() => {${target} = ${exp};});`);
1492
+ const exp = astring.generate(ex.right);
1493
+ watchers.push(xNode('watch-assign', {
1494
+ $wait: ['apply'],
1495
+ target,
1496
+ exp
1497
+ }, (ctx, n) => {
1498
+ if(this.inuse.apply) ctx.write(true, `$runtime.prefixPush(() => {${n.target} = ${n.exp};});`);
1499
+ else ctx.write(true, `${n.target} = ${n.exp};`);
1500
+ }));
1491
1501
  } else if(n.body.expression.type == 'SequenceExpression') {
1492
1502
  const ex = n.body.expression.expressions;
1493
- const handler = ex[ex.length - 1];
1494
- let callback = source.substring(handler.start, handler.end);
1503
+ const handler = last(ex);
1504
+ let callback = astring.generate(handler);
1495
1505
  if(handler.type == 'ArrowFunctionExpression' || handler.type == 'FunctionExpression') ; else if(detectExpressionType(callback) == 'identifier') {
1496
1506
  callback = `(v) => { ${callback}(v); }`;
1497
1507
  } else {
@@ -1500,13 +1510,33 @@
1500
1510
 
1501
1511
  if(ex.length == 2) {
1502
1512
  assertExpression(ex[0]);
1503
- let exp = source.substring(ex[0].start, ex[0].end);
1504
- if(this.config.immutable) result.watchers.push(`$watch(() => (${exp}), ${callback}, {ro: false});`);
1505
- else result.watchers.push(`$watch(() => (${exp}), ${callback}, {ro: false, cmp: $runtime.$$deepComparator(0)});`);
1513
+ watchers.push(xNode('watch-expression', {
1514
+ $wait: ['apply'],
1515
+ exp: astring.generate(ex[0]),
1516
+ callback
1517
+ }, (ctx, n) => {
1518
+ if(this.inuse.apply) {
1519
+ if(this.config.immutable) ctx.write(true, `$watch(() => (${n.exp}), ${n.callback});`);
1520
+ else ctx.write(true, `$watch(() => (${n.exp}), ${n.callback}, {cmp: $runtime.$$deepComparator(0)});`);
1521
+ } else {
1522
+ ctx.write(true, `(${n.callback})(${n.exp});`);
1523
+ }
1524
+ }));
1506
1525
  } else if(ex.length > 2) {
1507
1526
  for(let i = 0; i < ex.length - 1; i++) assertExpression(ex[i]);
1508
- let exp = source.substring(ex[0].start, ex[ex.length - 2].end);
1509
- result.watchers.push(`$watch(() => [${exp}], ($args) => { (${callback}).apply(null, $args); }, {ro: false, cmp: $runtime.$$deepComparator(1)});`);
1527
+ let exp = {
1528
+ type: 'ArrayExpression',
1529
+ elements: ex.slice(0, ex.length - 1)
1530
+ };
1531
+
1532
+ watchers.push(xNode('watch-expression', {
1533
+ $wait: ['apply'],
1534
+ exp: astring.generate(exp),
1535
+ callback
1536
+ }, (ctx, n) => {
1537
+ if(this.inuse.apply) ctx.write(true, `$watch(() => ${n.exp}, ($args) => { (${n.callback}).apply(null, $args); }, {cmp: $runtime.$$deepComparator(1)});`);
1538
+ else ctx.write(true, `(${n.callback}).apply(null, ${n.exp})`);
1539
+ }));
1510
1540
  } else throw 'Error';
1511
1541
  } else throw 'Error';
1512
1542
  };
@@ -1528,6 +1558,8 @@
1528
1558
  });
1529
1559
  }
1530
1560
 
1561
+ let exportedFunctions = [];
1562
+
1531
1563
  ast.body.forEach(n => {
1532
1564
  if(n.type == 'ImportDeclaration') {
1533
1565
  imports.push(n);
@@ -1543,8 +1575,14 @@
1543
1575
  });
1544
1576
  return;
1545
1577
  } else if(n.type == 'ExportNamedDeclaration') {
1546
- if(n.declaration.kind != 'const') constantProps = false;
1578
+ if(n.declaration.type == 'FunctionDeclaration') {
1579
+ exportedFunctions.push(n.declaration.id.name);
1580
+ resultBody.push(n.declaration);
1581
+ return;
1582
+ }
1583
+
1547
1584
  assert(n.declaration.type == 'VariableDeclaration', 'Wrong export');
1585
+ if(n.declaration.kind != 'const') constantProps = false;
1548
1586
  n.declaration.declarations.forEach(d => {
1549
1587
  assert(d.type == 'VariableDeclarator', 'Wrong export');
1550
1588
  let p = { name: d.id.name };
@@ -1634,6 +1672,7 @@
1634
1672
  }));
1635
1673
 
1636
1674
  this.module.top.push(xNode('ast', { body: imports }));
1675
+ this.module.code.push(watchers);
1637
1676
 
1638
1677
  if(this.scriptNodes[0] && this.scriptNodes[0].attributes.some(a => a.name == 'property') && this.script.props.length && !this.script.readOnly) {
1639
1678
  this.require('apply');
@@ -1645,6 +1684,16 @@
1645
1684
  });
1646
1685
  }));
1647
1686
  }
1687
+
1688
+ this.module.code.push(xNode('exported-functions', {
1689
+ $hold: ['$component'],
1690
+ list: exportedFunctions
1691
+ }, (ctx, n) => {
1692
+ if(!n.list.length) return;
1693
+ this.require('$component');
1694
+ for(let name of n.list)
1695
+ ctx.write(true, `$component.${name} = ${name};`);
1696
+ }));
1648
1697
  }
1649
1698
 
1650
1699
 
@@ -1756,23 +1805,40 @@
1756
1805
  let bb = this.buildBlock(this.DOM, {
1757
1806
  inline: true,
1758
1807
  protectLastTag: true,
1808
+ allowSingleBlock: true,
1759
1809
  template: {
1760
1810
  name: '$parentElement',
1761
1811
  cloneNode: true
1762
1812
  }
1763
1813
  });
1764
- runtime.push(bb.template);
1765
- runtime.push(xNode('root-event', (ctx) => {
1766
- if(!this.inuse.rootEvent) return;
1767
- ctx.write(true, 'const $$addRootEvent = $runtime.makeRootEvent($parentElement);');
1768
- }));
1769
- runtime.push(bb.source);
1814
+ if(bb.singleBlock) {
1815
+ runtime.push(xNode('attach-block', {
1816
+ block: bb.singleBlock,
1817
+ reference: bb.reference
1818
+ }, (ctx, n) => {
1819
+ if(n.reference) {
1820
+ ctx.write(true, `${n.reference} = `);
1821
+ ctx.add(n.block);
1822
+ ctx.write(';');
1823
+ ctx.write(true, `let $parentElement = ${n.reference}.$dom;`);
1824
+ } else {
1825
+ ctx.write(true, `let $parentElement = `);
1826
+ ctx.add(n.block);
1827
+ ctx.write('.$dom;');
1828
+ }
1829
+ }));
1830
+ } else {
1831
+ runtime.push(bb.template);
1832
+ runtime.push(xNode('root-event', (ctx) => {
1833
+ if(!this.inuse.rootEvent) return;
1834
+ ctx.write(true, 'const $$addRootEvent = $runtime.makeRootEvent($parentElement);');
1835
+ }));
1836
+ runtime.push(bb.source);
1837
+ }
1838
+
1770
1839
 
1771
1840
  if(this.script.onMount) runtime.push('$runtime.$onMount(onMount);');
1772
1841
  if(this.script.onDestroy) runtime.push('$runtime.$onDestroy(onDestroy);');
1773
- if(this.script.watchers.length) {
1774
- this.script.watchers.forEach(n => runtime.push(n));
1775
- }
1776
1842
 
1777
1843
  runtime.push(xNode('addStyle', ctx => {
1778
1844
  if(!this.css.active()) return;
@@ -1831,13 +1897,21 @@
1831
1897
 
1832
1898
  if(option.each?.blockPrefix) binds.push(option.each.blockPrefix);
1833
1899
 
1834
- if(option.allowSingleBlock && data.body.length == 1) {
1835
- let n = data.body[0];
1836
- if(n.type == 'node' && n.name.match(/^[A-Z]/)) {
1837
- let component = this.makeComponent(n);
1838
- return {
1839
- singleBlock: component.bind
1840
- };
1900
+ if(option.allowSingleBlock) {
1901
+ let nodesForSingleBlock = data.body.filter(n => {
1902
+ if(n.type == 'comment' && !this.config.preserveComments) return false;
1903
+ return true;
1904
+ });
1905
+
1906
+ if(nodesForSingleBlock.length == 1) {
1907
+ let n = nodesForSingleBlock[0];
1908
+ if(n.type == 'node' && n.name.match(/^[A-Z]/)) {
1909
+ let component = this.makeComponent(n);
1910
+ return {
1911
+ singleBlock: component.bind,
1912
+ reference: component.reference
1913
+ };
1914
+ }
1841
1915
  }
1842
1916
  }
1843
1917
 
@@ -1943,7 +2017,7 @@
1943
2017
  if(!exp.endsWith(';')) exp += ';';
1944
2018
  binds.push(xNode('block', {
1945
2019
  body: [
1946
- replaceElementKeyword(exp, () => textNode.bindName())
2020
+ replaceKeyword(exp, (name) => name == '$element' ? textNode.bindName() : null)
1947
2021
  ]
1948
2022
  }));
1949
2023
  });
@@ -1980,11 +2054,18 @@
1980
2054
  let component = this.makeComponent(n);
1981
2055
  binds.push(xNode('insert-component', {
1982
2056
  component: component.bind,
2057
+ reference: component.reference,
1983
2058
  el: el.bindName()
1984
2059
  }, (ctx, n) => {
1985
- ctx.write(true, `$runtime.insertAfter(${n.el}, `);
1986
- ctx.add(n.component);
1987
- ctx.write('.$dom);');
2060
+ if(n.reference) {
2061
+ ctx.write(true, `${n.reference} = `);
2062
+ ctx.add(n.component);
2063
+ ctx.write(true, `$runtime.attachBlock(${n.el}, ${n.reference});`);
2064
+ } else {
2065
+ ctx.write(true, `$runtime.attachBlock(${n.el}, `);
2066
+ ctx.add(n.component);
2067
+ ctx.write(');');
2068
+ }
1988
2069
  }));
1989
2070
  }
1990
2071
  } else {
@@ -4401,7 +4482,10 @@
4401
4482
  let n = new Node(e.name, { __node: e });
4402
4483
  e.attributes.forEach(a => {
4403
4484
  if(a.name == 'class') {
4404
- if(a.value != null) n.className += ' ' + a.value;
4485
+ if(a.value != null) {
4486
+ if(a.value.includes('{')) n.dynClass = true;
4487
+ else n.className += ' ' + a.value;
4488
+ }
4405
4489
  n.attributes[a.name] = a.value;
4406
4490
  } else if(a.name == 'id') n.attributes.id = n.id = a.value;
4407
4491
  else if(a.name.startsWith('class:')) {
@@ -4481,18 +4565,20 @@
4481
4565
  if(names.length != 1) throw 'Not supported';
4482
4566
  let cls = names[0];
4483
4567
 
4568
+ let rx = RegExp('(^|\\s)' + cls + '(\\s|$)', 'i');
4484
4569
  let result = [];
4485
- this.childNodes.forEach(n => {
4486
- let rx = RegExp('(^|\\s)' + cls + '(\\s|$)', 'i');
4487
- if(rx.test(n.className)) result.push(n);
4488
- result.push.apply(result, n.getElementsByClassName(cls));
4489
- });
4570
+ const walk = (node) => {
4571
+ node.childNodes.forEach(n => {
4572
+ if(n.dynClass) result.push(n);
4573
+ else if(rx.test(n.className)) result.push(n);
4574
+ walk(n);
4575
+ });
4576
+ };
4577
+ walk(this);
4490
4578
  return result;
4491
4579
  };
4492
4580
 
4493
4581
  function makeComponent(node) {
4494
- this.require('apply');
4495
-
4496
4582
  let propList = node.attributes;
4497
4583
 
4498
4584
  this.require('$context');
@@ -4505,7 +4591,7 @@
4505
4591
  let componentName = node.name;
4506
4592
  if(componentName != 'component' && this.config.autoimport) {
4507
4593
  let imported = this.script.autoimport[componentName] || this.script.importedNames.includes(componentName) ||
4508
- this.script.rootVariables[componentName] || this.script.rootFunctions[componentName];
4594
+ this.script.rootVariables[componentName] || this.script.rootFunctions[componentName];
4509
4595
 
4510
4596
  if(!imported) {
4511
4597
  let r = this.config.autoimport(componentName, this.config.path, this);
@@ -4590,7 +4676,7 @@
4590
4676
  if(n.props) ctx.write(', $localProps');
4591
4677
  ctx.write(') => {', true);
4592
4678
  ctx.indent++;
4593
- if(n.props) ctx.write(true, `let {${n.props.join(', ')}} = $localProps;`);
4679
+ if(n.props) ctx.write(true, `let {${n.props.join(', ')}} = $localProps || {};`);
4594
4680
  ctx.add(n.bind);
4595
4681
 
4596
4682
  if(n.props && this.inuse.apply) ctx.write(true, `return ($localProps) => ({${n.props.join(', ')}} = $localProps, $$apply());`);
@@ -4732,14 +4818,12 @@
4732
4818
  staticProps,
4733
4819
  props: propsFn,
4734
4820
  propsSetter,
4735
- reference,
4736
4821
  $class,
4737
4822
  forwardAllEvents,
4738
4823
  events,
4739
4824
  slots: slotBlocks.length ? slotBlocks : null,
4740
4825
  anchors: anchorBlocks.length ? anchorBlocks : null
4741
4826
  }, (ctx, n) => {
4742
- if(n.reference) throw 'not implemented'; // FIXME
4743
4827
  let comma = false;
4744
4828
  ctx.write(`$runtime.callComponent($context, ${n.componentName}, {`);
4745
4829
 
@@ -4803,6 +4887,11 @@
4803
4887
  ctx.indent--;
4804
4888
  ctx.write(true, '}');
4805
4889
  }
4890
+ if(n.$class.length && !ctx.inuse.apply) {
4891
+ if(comma) ctx.write(', ');
4892
+ comma = true;
4893
+ ctx.write(`$class: {${n.$class.join(', ')}}`);
4894
+ }
4806
4895
  ctx.write('}');
4807
4896
 
4808
4897
  let other = '';
@@ -4824,7 +4913,7 @@
4824
4913
  ctx.write(',\n', true, `($$_value) => ({${n.propsSetter.join(', ')}} = $$_value)`);
4825
4914
  } else other += ', null';
4826
4915
 
4827
- if(n.$class.length) {
4916
+ if(n.$class.length && ctx.inuse.apply) {
4828
4917
  if(other) ctx.write(other);
4829
4918
  other = '';
4830
4919
  ctx.write(',\n', true, `() => ({${n.$class.join(', ')}})`);
@@ -4834,7 +4923,7 @@
4834
4923
  ctx.write(true, ')');
4835
4924
  });
4836
4925
 
4837
- return { bind: result };
4926
+ return { bind: result, reference };
4838
4927
  }
4839
4928
 
4840
4929
  function makeComponentDyn(node, element) {
@@ -4852,17 +4941,20 @@
4852
4941
  }
4853
4942
 
4854
4943
  assert(dynamicComponent);
4944
+ this.require('apply');
4855
4945
  this.detectDependency(dynamicComponent);
4856
4946
 
4857
- let component = this.makeComponent(node).bind;
4947
+ let {bind: component, reference} = this.makeComponent(node);
4858
4948
 
4859
4949
  component.componentName = '$ComponentConstructor';
4860
4950
  return xNode('dyn-component', {
4861
4951
  el: element.bindName(),
4862
4952
  exp: dynamicComponent,
4863
- component
4953
+ component,
4954
+ reference
4864
4955
  }, (ctx, n) => {
4865
4956
  ctx.write(true, `$runtime.attachDynComponent(${n.el}, () => ${n.exp}, ($ComponentConstructor) => `);
4957
+ if(n.reference) ctx.write(`${n.reference} = `);
4866
4958
  ctx.add(n.component);
4867
4959
  ctx.write(')');
4868
4960
  });
@@ -4879,7 +4971,7 @@
4879
4971
  return {
4880
4972
  bind: xNode('block', {
4881
4973
  body: [
4882
- replaceElementKeyword(exp, () => element.bindName())
4974
+ replaceKeyword(exp, (name) => name == '$element' ? element.bindName() : null)
4883
4975
  ]
4884
4976
  })
4885
4977
  };
@@ -5382,15 +5474,8 @@
5382
5474
  right = right.trim();
5383
5475
 
5384
5476
  const makeKeyFunction = (keyLink) => {
5385
- const e = parseJS(keyName).transform((n, pk) => {
5386
- if(n.type != 'Identifier') return;
5387
- if(pk == 'property') return;
5388
- let r = keyLink[n.name];
5389
- if(r) n.name = r;
5390
- });
5391
- let exp = e.build(e.ast.body[0].expression);
5392
5477
  keyFunction = xNode('key-function', {
5393
- exp
5478
+ exp: replaceKeyword(keyName, n => keyLink[n])
5394
5479
  }, (ctx, n) => {
5395
5480
  ctx.write(`($$item, $index) => ${n.exp}`);
5396
5481
  });
@@ -5402,22 +5487,19 @@
5402
5487
  try {
5403
5488
  let exp = `[${right}]`;
5404
5489
  let e = parseJS(exp);
5405
- assert(e.ast.body.length == 1);
5406
-
5490
+ assert(e.ast.elements.length == 1 || e.ast.elements.length == 2);
5407
5491
  itemName = '$$item';
5408
- let n = e.ast.body[0];
5409
- assert(n.expression.elements.length == 1 || n.expression.elements.length == 2);
5410
- let a = n.expression.elements[0];
5411
- unwrap = exp.substring(a.start, a.end);
5412
-
5413
- if(n.expression.elements.length == 2) {
5414
- let b = n.expression.elements[1];
5492
+
5493
+ unwrap = e.build(e.ast.elements[0]);
5494
+
5495
+ if(e.ast.elements.length == 2) {
5496
+ let b = e.ast.elements[1];
5415
5497
  assert(b.type == 'Identifier');
5416
- indexName = exp.substring(b.start, b.end);
5498
+ indexName = e.build(b);
5417
5499
  }
5418
5500
 
5419
5501
  e = parseJS(`(${unwrap} = $$item)`);
5420
- let l = e.ast.body[0].expression.left;
5502
+ let l = e.ast.left;
5421
5503
  if(l.type == 'ArrayPattern') {
5422
5504
  keywords = l.elements.map(p => p.name);
5423
5505
 
@@ -5653,7 +5735,7 @@
5653
5735
  }, (ctx, n) => {
5654
5736
  let dynamicProps = this.inuse.apply && !n.staticProps;
5655
5737
 
5656
- let missed = '', slotName = n.name == 'default' ? 'null' : n.name;
5738
+ let missed = '', slotName = n.name == 'default' ? 'null' : `'${n.name}'`;
5657
5739
  if(dynamicProps) ctx.write(`$runtime.invokeSlot($component, ${slotName}, $context`);
5658
5740
  else ctx.write(`$runtime.invokeSlotBase($component, ${slotName}, $context`);
5659
5741
 
@@ -6171,7 +6253,9 @@
6171
6253
  if(prop.value) {
6172
6254
  assert$1(!handler);
6173
6255
  exp = unwrapExp(prop.value);
6174
- exp = replaceElementKeyword(exp, requireElement);
6256
+ exp = replaceKeyword(exp, (name) => {
6257
+ if(name == '$element') return requireElement();
6258
+ });
6175
6259
  } else if(!handler) handler = event;
6176
6260
 
6177
6261
  this.detectDependency(exp || handler);
@@ -6270,7 +6354,7 @@
6270
6354
  return { event, fn, rootModifier };
6271
6355
  }
6272
6356
 
6273
- const version = '0.7.0-a5';
6357
+ const version = '0.7.0-a8';
6274
6358
 
6275
6359
 
6276
6360
  async function compile(source, config = {}) {
@@ -6395,7 +6479,7 @@
6395
6479
  await hook(ctx, 'js:before');
6396
6480
  ctx.js_parse();
6397
6481
  await hook(ctx, 'js');
6398
- ctx.js_transform();
6482
+ use_context(ctx, () => ctx.js_transform());
6399
6483
  await hook(ctx, 'js:after');
6400
6484
 
6401
6485
  await hook(ctx, 'css:before');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malinajs",
3
- "version": "0.7.0-a5",
3
+ "version": "0.7.0-a8",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "prepare": "npm run build",
package/runtime.js CHANGED
@@ -30,7 +30,6 @@ const $onDestroy = fn => fn && current_destroyList.push(fn);
30
30
  function WatchObject(fn, cb) {
31
31
  this.fn = fn;
32
32
  this.cb = cb;
33
- this.ro = true;
34
33
  this.value = NaN;
35
34
  this.cmp = null;
36
35
  }
@@ -101,7 +100,6 @@ function $$compareArray(w, value) {
101
100
  if(isArray(value)) w.value = value.slice();
102
101
  else w.value = value;
103
102
  w.cb(w.value);
104
- return w.ro ? 0 : 1;
105
103
  }
106
104
 
107
105
 
@@ -159,7 +157,6 @@ function $$deepComparator(depth) {
159
157
  let diff = compareDeep(w.value, value, depth);
160
158
  diff && (w.value = cloneDeep(value, depth), !w.idle && w.cb(value));
161
159
  w.idle = false;
162
- return !w.ro && diff ? 1 : 0;
163
160
  };
164
161
  }
165
162
 
@@ -174,7 +171,6 @@ const keyComparator = (w, value) => {
174
171
  }
175
172
  diff && !w.idle && w.cb(value);
176
173
  w.idle = false;
177
- return !w.ro && diff ? 1 : 0;
178
174
  };
179
175
 
180
176
 
@@ -186,27 +182,26 @@ const fire = w => {
186
182
  }
187
183
  };
188
184
 
189
- function $digest($cd) {
185
+ function $digest($cd, flag) {
190
186
  let loop = 10;
191
187
  let w;
192
188
  while(loop >= 0) {
193
- let changes = 0;
194
189
  let index = 0;
195
190
  let queue = [];
196
- let i, value, cd = $cd;
191
+ let i, value, cd = $cd, changes = 0;
197
192
  while(cd) {
198
193
  for(i = 0; i < cd.prefix.length; i++) cd.prefix[i]();
199
194
  for(i = 0; i < cd.watchers.length; i++) {
200
195
  w = cd.watchers[i];
201
196
  value = w.fn();
202
197
  if(w.value !== value) {
198
+ flag[0] = 0;
203
199
  if(w.cmp) {
204
- changes += w.cmp(w, value);
200
+ w.cmp(w, value);
205
201
  } else {
206
- w.value = value;
207
- if(!w.ro) changes++;
208
- w.cb(w.value);
202
+ w.cb(w.value = value);
209
203
  }
204
+ changes += flag[0];
210
205
  }
211
206
  }
212
207
  if(cd.children.length) queue.push.apply(queue, cd.children);
@@ -356,13 +351,14 @@ const makeApply = () => {
356
351
  let $cd = current_component.$cd = current_cd = cd_new();
357
352
  $cd.component = current_component;
358
353
 
359
- let planned;
354
+ let planned, flag = [0];
360
355
  let apply = r => {
356
+ flag[0]++;
361
357
  if(planned) return r;
362
358
  planned = true;
363
359
  $tick(() => {
364
360
  try {
365
- $digest($cd);
361
+ $digest($cd, flag);
366
362
  } finally {
367
363
  planned = false;
368
364
  }
@@ -550,7 +546,7 @@ const bindAction = (element, action, fn, subscribe) => {
550
546
  } else handler = action(element);
551
547
  $onDestroy(handler?.destroy);
552
548
  subscribe?.(fn, handler, value);
553
- handler.init && $tick(handler.init);
549
+ handler?.init && $tick(handler.init);
554
550
  };
555
551
 
556
552
 
@@ -558,7 +554,7 @@ const __bindActionSubscribe = (fn, handler, value) => {
558
554
  if(handler?.update && fn) {
559
555
  $watch(fn, args => {
560
556
  handler.update.apply(handler, args);
561
- }, { ro: false, cmp: $$deepComparator(1), value: cloneDeep(value, 1) });
557
+ }, { cmp: $$deepComparator(1), value: cloneDeep(value, 1) });
562
558
  }
563
559
  };
564
560
 
@@ -810,6 +806,17 @@ const mount = (label, component, option) => {
810
806
  return app;
811
807
  };
812
808
 
809
+ const mountStatic = (label, component, option) => {
810
+ current_destroyList = [];
811
+ try {
812
+ let app = component(option);
813
+ label.appendChild(app.$dom);
814
+ return app;
815
+ } finally {
816
+ current_destroyList = null;
817
+ }
818
+ };
819
+
813
820
  let create = (tag, html) => {
814
821
  let fr;
815
822
  if(tag.parentElement instanceof SVGElement) {
@@ -1134,12 +1141,17 @@ const invokeSlot = ($component, slotName, $context, propsFn, placeholder, cmp) =
1134
1141
  let $slot = $component.$option.slots?.[slotName || 'default'];
1135
1142
 
1136
1143
  if($slot) {
1137
- let push, $dom,
1138
- w = new WatchObject(propsFn, value => push(value));
1144
+ let push, w = new WatchObject(propsFn, value => push(value));
1139
1145
  Object.assign(w, {value: {}, cmp, idle: true});
1140
1146
  fire(w);
1141
- ([$dom, push] = $slot($component, $context, w.value));
1142
- if(push) current_cd.watchers.push(w);
1147
+ let $dom = $slot($component, $context, w.value);
1148
+ if($dom.$dom) {
1149
+ if($dom.push) {
1150
+ push = $dom.push;
1151
+ current_cd.watchers.push(w);
1152
+ }
1153
+ $dom = $dom.$dom;
1154
+ }
1143
1155
  return $dom;
1144
1156
  } else return placeholder?.();
1145
1157
  };
@@ -1150,12 +1162,13 @@ const makeSlot = (fr, fn) => {
1150
1162
  let $dom = fr.cloneNode(true), prev = current_cd, $cd = current_cd = cd_new();
1151
1163
  cd_attach2(parentCD, $cd);
1152
1164
  $onDestroy(() => cd_detach($cd));
1165
+ parentCD.component.apply();
1153
1166
  try {
1154
- return [$dom, fn($dom, $context, callerComponent, props)];
1167
+ return {$dom, push: fn($dom, $context, callerComponent, props)};
1155
1168
  } finally {
1156
1169
  current_cd = prev;
1157
1170
  }
1158
1171
  };
1159
1172
  };
1160
1173
 
1161
- export { $$addEventForComponent, $$awaitBlock, $$cloneDeep, $$compareArray, $$compareDeep, $$deepComparator, $$eachBlock, $$htmlBlock, $$htmlBlockStatic, $$htmlToFragment, $$htmlToFragmentClean, $$removeElements, $$removeItem, $context, $digest, $makeEmitter, $onDestroy, $onMount, $tick, $watch, WatchObject, __app_onerror, __bindActionSubscribe, addClass, addEvent, addStyles, attachAnchor, attachBlock, attachDynComponent, autoSubscribe, bindAction, bindAttribute, bindAttributeBase, bindClass, bindClassExp, bindInput, bindStyle, bindText, callComponent, callExportedFragment, cd_attach, cd_attach2, cd_component, cd_detach, cd_new, childNodes, cloneDeep, configure, createTextNode, current_cd, current_component, current_destroyList, destroyResults, eachDefaultKey, exportFragment, fire, firstChild, getFinalLabel, ifBlock, ifBlockReadOnly, insertAfter, invokeSlot, invokeSlotBase, isArray, isFunction, iterNodes, keyComparator, makeAnchor, makeApply, makeBlock, makeBlockBound, makeClassResolver, makeComponent, makeEachBlock, makeEachSingleBlock, makeExternalProperty, makeRootEvent, makeSlot, mergeEvents, mount, noop, prefixPush, removeElementsBetween, setClassToElement, spreadAttributes, svgToFragment, unwrapProps };
1174
+ export { $$addEventForComponent, $$awaitBlock, $$cloneDeep, $$compareArray, $$compareDeep, $$deepComparator, $$eachBlock, $$htmlBlock, $$htmlBlockStatic, $$htmlToFragment, $$htmlToFragmentClean, $$removeElements, $$removeItem, $context, $digest, $makeEmitter, $onDestroy, $onMount, $tick, $watch, WatchObject, __app_onerror, __bindActionSubscribe, addClass, addEvent, addStyles, attachAnchor, attachBlock, attachDynComponent, autoSubscribe, bindAction, bindAttribute, bindAttributeBase, bindClass, bindClassExp, bindInput, bindStyle, bindText, callComponent, callExportedFragment, cd_attach, cd_attach2, cd_component, cd_detach, cd_new, childNodes, cloneDeep, configure, createTextNode, current_cd, current_component, current_destroyList, destroyResults, eachDefaultKey, exportFragment, fire, firstChild, getFinalLabel, ifBlock, ifBlockReadOnly, insertAfter, invokeSlot, invokeSlotBase, isArray, isFunction, iterNodes, keyComparator, makeAnchor, makeApply, makeBlock, makeBlockBound, makeClassResolver, makeComponent, makeEachBlock, makeEachSingleBlock, makeExternalProperty, makeRootEvent, makeSlot, mergeEvents, mount, mountStatic, noop, prefixPush, removeElementsBetween, setClassToElement, spreadAttributes, svgToFragment, unwrapProps };