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