bobe 0.0.59 → 0.0.61

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/dist/bobe.esm.js CHANGED
@@ -33,15 +33,15 @@ let FakeType = function (FakeType) {
33
33
  FakeType[FakeType["ForItem"] = 64] = "ForItem";
34
34
  FakeType[FakeType["Context"] = 128] = "Context";
35
35
  FakeType[FakeType["DynamicText"] = 256] = "DynamicText";
36
+ FakeType[FakeType["Tp"] = 512] = "Tp";
36
37
  return FakeType;
37
38
  }({});
38
39
  const CondBit = FakeType.If | FakeType.Fail | FakeType.Else;
39
- const LogicalBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem;
40
40
  const CtxProviderBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem | FakeType.Component | FakeType.Fragment | FakeType.DynamicText;
41
- const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context;
41
+ const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context | FakeType.Tp;
42
42
  const TokenizerSwitcherBit = FakeType.Component | FakeType.Fragment;
43
43
  let NodeSort = function (NodeSort) {
44
- NodeSort[NodeSort["Logic"] = 1] = "Logic";
44
+ NodeSort[NodeSort["EffectNode"] = 1] = "EffectNode";
45
45
  NodeSort[NodeSort["Real"] = 2] = "Real";
46
46
  NodeSort[NodeSort["Component"] = 4] = "Component";
47
47
  NodeSort[NodeSort["CtxProvider"] = 8] = "CtxProvider";
@@ -54,6 +54,7 @@ let NodeSort = function (NodeSort) {
54
54
  TerpEvt["HandledComponentNode"] = "handled-component-node";
55
55
  return TerpEvt;
56
56
  })({});
57
+ const FakeNode = Symbol('fake-node');
57
58
  let ParseErrorCode = function (ParseErrorCode) {
58
59
  ParseErrorCode[ParseErrorCode["UNCLOSED_BRACE"] = 9001] = "UNCLOSED_BRACE";
59
60
  ParseErrorCode[ParseErrorCode["UNCLOSED_STRING"] = 9002] = "UNCLOSED_STRING";
@@ -1429,6 +1430,14 @@ class InlineFragment {
1429
1430
  }
1430
1431
  const isUI = fn => typeof fn === 'function' && fn.__BOBE_IS_UI;
1431
1432
  const isRenderAble = val => isStore(val) || isUI(val) || val instanceof InlineFragment;
1433
+ const SAFE_HANDLER = {
1434
+ has: () => true,
1435
+ get: (t, k) => {
1436
+ if (typeof k === 'symbol') return t[k];
1437
+ return k in t ? t[k] : undefined;
1438
+ }
1439
+ };
1440
+ const safe = data => new Proxy(data, SAFE_HANDLER);
1432
1441
 
1433
1442
  const KEY_INDEX = '__BOBE_KEY_INDEX';
1434
1443
  let _ctxStack;
@@ -1440,9 +1449,6 @@ class Interpreter {
1440
1449
  constructor(tokenizer) {
1441
1450
  this.tokenizer = tokenizer;
1442
1451
  }
1443
- isLogicNode(node) {
1444
- return node && node.__logicType & LogicalBit;
1445
- }
1446
1452
  rootComponent = null;
1447
1453
  program(root, componentNode, before, ctxProvider) {
1448
1454
  this.rootComponent = componentNode;
@@ -1461,7 +1467,7 @@ class Interpreter {
1461
1467
  stack.push({
1462
1468
  node: ctxProvider,
1463
1469
  prev: null
1464
- }, (ctxProvider.__logicType & LogicalBit ? NodeSort.Logic : 0) | NodeSort.CtxProvider);
1470
+ }, (ctxProvider.__logicType && ctxProvider.effect ? NodeSort.EffectNode : 0) | NodeSort.CtxProvider);
1465
1471
  }
1466
1472
  const rootLen = stack.length;
1467
1473
  const ctx = this.ctx = {
@@ -1484,18 +1490,22 @@ class Interpreter {
1484
1490
  const token = this.tokenizer.token;
1485
1491
  if (token.type & TokenType.Indent) {
1486
1492
  this.tokenizer.nextToken();
1487
- const isLogicNode = this.isLogicNode(ctx.current);
1493
+ const isEffectNode = ctx.current && ctx.current.__logicType && ctx.current.effect;
1488
1494
  stack.push({
1489
1495
  node: ctx.current,
1490
1496
  prev: ctx.prevSibling
1491
- }, !ctx.current.__logicType ? NodeSort.Real : (ctx.current.__logicType & LogicalBit ? NodeSort.Logic : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType & ContextBit ? NodeSort.Context : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | (ctx.current.__logicType & CtxProviderBit ? NodeSort.CtxProvider : 0));
1497
+ }, !ctx.current.__logicType ? NodeSort.Real : (isEffectNode ? NodeSort.EffectNode : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType & ContextBit ? NodeSort.Context : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | (ctx.current.__logicType & CtxProviderBit ? NodeSort.CtxProvider : 0));
1492
1498
  if (ctx.current.__logicType) {
1493
1499
  this.beforeLogicIndent?.(ctx.current);
1494
- if (isLogicNode) {
1500
+ if (isEffectNode) {
1495
1501
  setPulling(ctx.current.effect);
1496
1502
  if (ctx.current.__logicType & FakeType.ForItem) {
1497
1503
  ctx.prevSibling = ctx.current.realBefore;
1498
1504
  }
1505
+ if (ctx.current.__logicType & FakeType.Tp) {
1506
+ ctx.realParent = ctx.current.tpData[Keys.Raw].node;
1507
+ ctx.prevSibling = ctx.current.contentBefore;
1508
+ }
1499
1509
  }
1500
1510
  } else {
1501
1511
  if (ctx.current) {
@@ -1531,14 +1541,17 @@ class Interpreter {
1531
1541
  const prevSameType = stack.peekByType(NodeSort.Real);
1532
1542
  ctx.realParent = prevSameType?.node || root;
1533
1543
  } else {
1534
- if (sort & NodeSort.Logic) {
1535
- const parentLogic = stack.peekByType(NodeSort.Logic)?.node;
1544
+ if (sort & NodeSort.EffectNode) {
1545
+ const parentLogic = stack.peekByType(NodeSort.EffectNode)?.node;
1536
1546
  if (parentLogic) {
1537
1547
  setPulling(parentLogic.effect);
1538
1548
  } else {
1539
1549
  setPulling(rootPulling);
1540
1550
  }
1541
1551
  }
1552
+ if (parent.__logicType === FakeType.Tp) {
1553
+ ctx.realParent = parent.realParent;
1554
+ }
1542
1555
  if (sort & NodeSort.TokenizerSwitcher) {
1543
1556
  const switcher = stack.peekByType(NodeSort.TokenizerSwitcher)?.node;
1544
1557
  if (parent.resumeSnapshot) {
@@ -1575,13 +1588,17 @@ class Interpreter {
1575
1588
  }
1576
1589
  return componentNode;
1577
1590
  }
1578
- insertAnchor(name = 'anchor', isBefore = false) {
1591
+ insertAnchor(node, name = 'anchor', isBefore = false) {
1579
1592
  const _this$ctx = this.ctx,
1580
1593
  realParent = _this$ctx.realParent,
1581
1594
  prevSibling = _this$ctx.prevSibling,
1582
1595
  stack = _this$ctx.stack,
1583
1596
  before = _this$ctx.before;
1597
+ _this$ctx.current;
1584
1598
  const afterAnchor = this.createAnchor(name, isBefore);
1599
+ if (!isBefore) {
1600
+ this.anchorRefBack(afterAnchor, node);
1601
+ }
1585
1602
  this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
1586
1603
  this.handleInsert(realParent, afterAnchor, prevSibling);
1587
1604
  return afterAnchor;
@@ -1626,6 +1643,8 @@ class Interpreter {
1626
1643
  return this.condDeclaration(ctx);
1627
1644
  } else if (value === 'context') {
1628
1645
  _node = this.createContextNode();
1646
+ } else if (value === 'tp') {
1647
+ return this.createTpNode();
1629
1648
  } else if (value === 'for') {
1630
1649
  return this.forDeclaration();
1631
1650
  } else if (hookType) {
@@ -1665,11 +1684,11 @@ class Interpreter {
1665
1684
  effect: null,
1666
1685
  textNode: null,
1667
1686
  owner: ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node,
1668
- snapshot: this.tokenizer.snapshot(['dentStack']),
1687
+ snapshot: this.tokenizer.snapshot(['dentStack', 'isFirstToken']),
1669
1688
  parentDataProvider: ctx.stack.peekByType(NodeSort.CtxProvider)?.node
1670
1689
  };
1671
1690
  let isUpdate = false;
1672
- node.realAfter = this.insertAnchor(`dynamic-after`);
1691
+ node.realAfter = this.insertAnchor(node, `dynamic-after`);
1673
1692
  node.effect = this.effect(({
1674
1693
  old,
1675
1694
  val
@@ -1678,7 +1697,7 @@ class Interpreter {
1678
1697
  oldTextNode = node.textNode;
1679
1698
  if (oldLogicType) {
1680
1699
  this.removeLogicNode(node);
1681
- pickInPlace(node, ['realParent', 'realBefore', 'realAfter',, 'owner', 'snapshot', 'parentDataProvider']);
1700
+ pickInPlace(node, ['realParent', 'realBefore', 'realAfter', 'owner', 'snapshot', 'parentDataProvider']);
1682
1701
  }
1683
1702
  if (isRenderAble(val)) {
1684
1703
  if (oldTextNode) {
@@ -1708,7 +1727,7 @@ class Interpreter {
1708
1727
  }
1709
1728
  if (isUpdate) {
1710
1729
  this.tokenizer.useDedentAsEof = false;
1711
- this.program(node.realParent, node.owner, node.realBefore, node);
1730
+ this.program(node.realParent, node, node.realBefore);
1712
1731
  } else {
1713
1732
  this.tokenizer.useDedentAsEof = true;
1714
1733
  this.tokenizer.initIndentWhenUseDedentAsEof();
@@ -1749,6 +1768,93 @@ class Interpreter {
1749
1768
  });
1750
1769
  return node;
1751
1770
  }
1771
+ createTpNode() {
1772
+ const child = deepSignal({}, getPulling());
1773
+ const node = {
1774
+ __logicType: FakeType.Tp,
1775
+ data: this.getData(),
1776
+ realParent: null,
1777
+ realBefore: null,
1778
+ realAfter: null,
1779
+ contentBefore: null,
1780
+ contentAfter: null,
1781
+ effect: null,
1782
+ snapshot: null,
1783
+ tpData: child,
1784
+ owner: this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node
1785
+ };
1786
+ this.onePropParsed = createStoreOnePropParsed(child);
1787
+ this.tokenizer.nextToken();
1788
+ this.headerLineAndExtensions(node);
1789
+ this.onePropParsed = this.oneRealPropParsed;
1790
+ node.realAfter = this.insertAnchor(node, 'tp-after');
1791
+ const before = node.contentBefore = this.createAnchor('tp-content-before', true);
1792
+ const after = node.contentAfter = this.createAnchor('tp-content-after', true);
1793
+ let firstRender = true;
1794
+ node.effect = this.effect(({
1795
+ old: oldDom,
1796
+ val: dom
1797
+ }) => {
1798
+ const removeTpChild = () => {
1799
+ if (oldDom) {
1800
+ let point = before;
1801
+ do {
1802
+ const next = this.nextSib(point);
1803
+ this.remove(point, oldDom, null);
1804
+ if (point === after) break;
1805
+ point = next;
1806
+ } while (true);
1807
+ }
1808
+ };
1809
+ if (firstRender) {
1810
+ if (dom) {
1811
+ this.handleInsert(dom, after, null);
1812
+ this.handleInsert(dom, before, null);
1813
+ } else {
1814
+ if (this.tokenizer.token.type === TokenType.Indent) {
1815
+ const dentLen = this.tokenizer.dentStack[this.tokenizer.dentStack.length - 2] ?? 0;
1816
+ this.tokenizer.skip(dentLen);
1817
+ }
1818
+ }
1819
+ } else {
1820
+ if (dom) {
1821
+ if (oldDom) {
1822
+ let point = before,
1823
+ lastInsert = null;
1824
+ do {
1825
+ const next = this.nextSib(point);
1826
+ const fakeNode = point[FakeNode];
1827
+ if (fakeNode) {
1828
+ fakeNode.realParent = dom;
1829
+ }
1830
+ this.handleInsert(dom, point, lastInsert);
1831
+ if (point === after) break;
1832
+ lastInsert = point;
1833
+ point = next;
1834
+ } while (true);
1835
+ } else {
1836
+ this.handleInsert(dom, after, null);
1837
+ this.handleInsert(dom, before, null);
1838
+ this.tokenizer = node.owner.tokenizer;
1839
+ this.tokenizer.resume(node.snapshot);
1840
+ this.tokenizer.useDedentAsEof = false;
1841
+ this.program(dom, node.owner, before, node);
1842
+ }
1843
+ } else {
1844
+ removeTpChild();
1845
+ }
1846
+ }
1847
+ firstRender = false;
1848
+ return isDestroy => {
1849
+ if (isDestroy) {
1850
+ removeTpChild();
1851
+ }
1852
+ };
1853
+ }, [() => child.node], {
1854
+ type: 'render'
1855
+ });
1856
+ return node;
1857
+ }
1752
1858
  createContextNode() {
1753
1859
  const child = deepSignal({}, getPulling());
1754
1860
  const parentContext = this.ctx.stack.peekByType(NodeSort.Context)?.node?.context;
@@ -1763,7 +1869,7 @@ class Interpreter {
1763
1869
  realBefore: null,
1764
1870
  realAfter: null
1765
1871
  };
1766
- node.realAfter = this.insertAnchor('context-after');
1872
+ node.realAfter = this.insertAnchor(node, 'context-after');
1767
1873
  return node;
1768
1874
  }
1769
1875
  formatForCollection(collection) {
@@ -1853,15 +1959,15 @@ class Interpreter {
1853
1959
  i: 0
1854
1960
  };
1855
1961
  if (keyExp) {
1856
- forNode.getKey = new Function('data', `let v;with(data){v=${keyExp}\n};return v;`);
1962
+ const rawGetKey = new Function('data', `with(data){return (${keyExp})}`);
1963
+ forNode.getKey = data => rawGetKey(safe(data));
1857
1964
  }
1858
- window['for1'] = forNode;
1859
1965
  const data = this.getData();
1860
1966
  const cells = data[Keys.Meta].cells;
1861
1967
  const hasArrExpKey = Reflect.has(data[Keys.Raw], arrExp);
1862
1968
  const arrSignal = hasArrExpKey ? (data[arrExp], cells.get(arrExp)) : new Computed(this.getFn(data, arrExp));
1863
1969
  forNode.arrSignal = arrSignal;
1864
- forNode.realAfter = this.insertAnchor('for-after');
1970
+ forNode.realAfter = this.insertAnchor(forNode, 'for-after');
1865
1971
  const _forNode$snapshot = forNode.snapshot;
1866
1972
  _forNode$snapshot.dentStack;
1867
1973
  _forNode$snapshot.isFirstToken;
@@ -1884,8 +1990,8 @@ class Interpreter {
1884
1990
  const len = arr.length;
1885
1991
  for (let i = len; i--;) {
1886
1992
  const item = this.createForItem(forNode, i, data);
1887
- item.realAfter = this.insertAnchor('for-item-after');
1888
- item.realBefore = this.insertAnchor('for-item-before', true);
1993
+ item.realAfter = this.insertAnchor(item, 'for-item-after');
1994
+ item.realBefore = this.insertAnchor(item, 'for-item-before', true);
1889
1995
  item.realParent = forNode.realParent;
1890
1996
  children[i] = item;
1891
1997
  }
@@ -2047,10 +2153,14 @@ class Interpreter {
2047
2153
  }, ScheduleType.Render);
2048
2154
  return forNode.children[0] || forNode;
2049
2155
  }
2156
+ anchorRefBack(anchor, node) {
2157
+ anchor[FakeNode] = node;
2158
+ }
2050
2159
  insertForItem(forNode, i, parentData, newChildren, before, snapshotForUpdate) {
2051
2160
  const item = this.createForItem(forNode, i, parentData);
2052
2161
  newChildren[i] = item;
2053
2162
  let realAfter = this.createAnchor('for-item-after');
2163
+ this.anchorRefBack(realAfter, item);
2054
2164
  this.handleInsert(forNode.realParent, realAfter, before);
2055
2165
  let realBefore = this.createAnchor('for-item-before', true);
2056
2166
  this.handleInsert(forNode.realParent, realBefore, before);
@@ -2221,11 +2331,11 @@ class Interpreter {
2221
2331
  resumeSnapshot
2222
2332
  };
2223
2333
  this.onePropParsed = onePropParsed;
2224
- node.realAfter = this.insertAnchor('component-after');
2334
+ node.realAfter = this.insertAnchor(node, 'component-after');
2225
2335
  return node;
2226
2336
  }
2227
2337
  getFn(data, expression) {
2228
- return new Function('data', `let v;with(data){v=${expression}};return v;`).bind(undefined, data);
2338
+ return new Function('data', `with(data){return (${expression})}`).bind(undefined, safe(data));
2229
2339
  }
2230
2340
  getAssignFn(data, expression) {
2231
2341
  const valueId = `value_bobe_${date32()}`;
@@ -2316,7 +2426,7 @@ class Interpreter {
2316
2426
  break;
2317
2427
  }
2318
2428
  ifNode.condition = signal;
2319
- ifNode.realAfter = this.insertAnchor(`${keyWord.value}-after`);
2429
+ ifNode.realAfter = this.insertAnchor(ifNode, `${keyWord.value}-after`);
2320
2430
  const ef = this.effect(({
2321
2431
  val
2322
2432
  }) => {
@@ -2359,10 +2469,11 @@ class Interpreter {
2359
2469
  const tokenizer = this.tokenizer;
2360
2470
  do {
2361
2471
  const isComponent = _node.__logicType & TokenizerSwitcherBit;
2472
+ const isTp = _node.__logicType === FakeType.Tp;
2362
2473
  let snapshot, dentLen;
2363
2474
  const data = this.getData();
2364
2475
  const unHandledKey = this.attributeList(_node, data);
2365
- if (isComponent) {
2476
+ if (isComponent || isTp) {
2366
2477
  snapshot = tokenizer.snapshot(undefined, -1);
2367
2478
  dentLen = tokenizer.dentStack[tokenizer.dentStack.length - 1];
2368
2479
  }
@@ -2374,6 +2485,9 @@ class Interpreter {
2374
2485
  if ((tokenizer.token.type & TokenType.Pipe) === 0) {
2375
2486
  break;
2376
2487
  }
2488
+ } else if (isTp) {
2489
+ _node.snapshot = snapshot;
2490
+ break;
2377
2491
  } else {
2378
2492
  break;
2379
2493
  }
@@ -2575,6 +2689,7 @@ function bobe(fragments, ...values) {
2575
2689
  return tokenizer;
2576
2690
  };
2577
2691
  ui.boundStore = Store.Current;
2692
+ ui[Keys.ProxyFreeObject] = true;
2578
2693
  ui.__BOBE_IS_UI = true;
2579
2694
  return ui;
2580
2695
  }