bobe 0.0.58 → 0.0.60

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/index.d.ts CHANGED
@@ -20,7 +20,7 @@ declare class Interpreter {
20
20
  ctx: ProgramCtx;
21
21
  rootComponent: ComponentNode$1 | null;
22
22
  program(root: any, componentNode?: ComponentNode$1, before?: any, ctxProvider?: any): ComponentNode$1;
23
- insertAfterAnchor(name?: string): any;
23
+ insertAnchor(name?: string, isBefore?: boolean): any;
24
24
  /** 处理
25
25
  * 是逻辑 是普通
26
26
  * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
@@ -97,12 +97,16 @@ declare class Interpreter {
97
97
  createNode(name: string): any;
98
98
  nextSib(node: any): any;
99
99
  firstChild(node: any): any;
100
- createAnchor(name: string): any;
100
+ createAnchor(name: string, isBefore?: boolean): any;
101
101
  insertAfter(parent: any, node: any, prev: any): void;
102
102
  defaultInsert(parent: any, node: any, prev: any): void;
103
103
  remove(node: any, parent?: any, prev?: any): void;
104
104
  defaultRemove(node: any, parent: any, prevSibling: any): void;
105
105
  setProp(node: any, key: string, value: any, hookI?: number): any | (() => void);
106
+ beforeIndent?: (node: any) => boolean | void;
107
+ leaveNode?: (node: any, isDedent: boolean) => void;
108
+ beforeLogicIndent?: (node: any) => void;
109
+ leaveLogicNode?: (node: any, isDedent: boolean) => void;
106
110
  Effect: typeof Effect;
107
111
  effect: typeof effect$1;
108
112
  }
@@ -193,10 +197,13 @@ type HookProps = {
193
197
  /** 父节点 */
194
198
  parentNode?: any;
195
199
  };
196
- type TerpConf = Partial<Pick<Interpreter, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib'>> & {
200
+ type TerpConf = Partial<Pick<Interpreter, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib' | 'beforeIndent' | 'leaveNode' | 'leaveLogicNode' | 'beforeLogicIndent'>> & {
197
201
  noopEffect?: boolean;
198
202
  };
199
- type CustomRenderConf = Pick<TerpConf, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib'>;
203
+ type CustomRenderConf = Pick<TerpConf, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib' | 'beforeIndent' | 'leaveNode' | 'leaveLogicNode' | 'beforeLogicIndent' | 'noopEffect'> & {
204
+ /** program() 之后、flushMicroEffectManual() 之前调用 */
205
+ onBeforeFlush?: () => void;
206
+ };
200
207
  type Hook = (props: HookProps) => any;
201
208
  type HookType = 'dynamic' | 'static';
202
209
  declare enum ParseErrorCode {
@@ -588,4 +595,4 @@ declare const context: IContext;
588
595
  declare const effect: (callback: (...args: ValueDiff[]) => void, depOrOpt?: Dep[] | Dep | CustomEffectOpt, opt?: CustomEffectOpt) => aoye.Effect;
589
596
 
590
597
  export { Compiler, FakeType, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
591
- export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
598
+ export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
package/dist/index.umd.js CHANGED
@@ -245,7 +245,6 @@
245
245
  }
246
246
  isEof() {
247
247
  if (!this.token) return false;
248
- if (this.i >= this.code.length && !this.waitingTokens.len) return true;
249
248
  return this.token.type & TokenType.Identifier && this.token.value === Tokenizer.EofId;
250
249
  }
251
250
  setToken(type, value, dt = 1) {
@@ -262,6 +261,7 @@
262
261
  if (this.isEof()) {
263
262
  return this.token;
264
263
  }
264
+ if (this.i >= this.code.length && !this.waitingTokens.len) return this.token;
265
265
  this.token = undefined;
266
266
  if (this.waitingTokens.len) {
267
267
  const item = this.waitingTokens.shift();
@@ -1431,6 +1431,14 @@
1431
1431
  }
1432
1432
  const isUI = fn => typeof fn === 'function' && fn.__BOBE_IS_UI;
1433
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);
1434
1442
 
1435
1443
  const KEY_INDEX = '__BOBE_KEY_INDEX';
1436
1444
  let _ctxStack;
@@ -1478,6 +1486,9 @@
1478
1486
  if (this.tokenizer.isEof()) {
1479
1487
  if (!ctx.prevSibling) ctx.prevSibling = before;
1480
1488
  this.handleInsert(root, ctx.current, ctx.prevSibling, componentNode);
1489
+ if (ctx.current) {
1490
+ ctx.current.__logicType ? this.leaveLogicNode?.(ctx.current, false) : this.leaveNode?.(ctx.current, false);
1491
+ }
1481
1492
  break;
1482
1493
  }
1483
1494
  const token = this.tokenizer.token;
@@ -1489,6 +1500,7 @@
1489
1500
  prev: ctx.prevSibling
1490
1501
  }, !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));
1491
1502
  if (ctx.current.__logicType) {
1503
+ this.beforeLogicIndent?.(ctx.current);
1492
1504
  if (isLogicNode) {
1493
1505
  aoye.setPulling(ctx.current.effect);
1494
1506
  if (ctx.current.__logicType & FakeType.ForItem) {
@@ -1497,6 +1509,12 @@
1497
1509
  }
1498
1510
  } else {
1499
1511
  if (ctx.current) {
1512
+ if (this.beforeIndent?.(ctx.current) === false) {
1513
+ const dentLen = this.tokenizer.dentStack[this.tokenizer.dentStack.length - 1];
1514
+ this.tokenizer.skip(dentLen);
1515
+ ctx.current = null;
1516
+ continue;
1517
+ }
1500
1518
  ctx.realParent = ctx.current;
1501
1519
  }
1502
1520
  ctx.prevSibling = null;
@@ -1509,6 +1527,7 @@
1509
1527
  ctx.prevSibling = before;
1510
1528
  }
1511
1529
  this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
1530
+ ctx.current.__logicType ? this.leaveLogicNode?.(ctx.current, false) : this.leaveNode?.(ctx.current, false);
1512
1531
  }
1513
1532
  if (this.tokenizer.token.type & TokenType.Dedent) {
1514
1533
  this.tokenizer.nextToken();
@@ -1543,6 +1562,7 @@
1543
1562
  const i = forNode.i,
1544
1563
  arr = forNode.arr,
1545
1564
  snapshot = forNode.snapshot;
1565
+ this.leaveLogicNode?.(parent, false);
1546
1566
  if (i + 1 < arr.length) {
1547
1567
  this.tokenizer.resume(snapshot);
1548
1568
  this.tokenizer.nextToken();
@@ -1565,13 +1585,13 @@
1565
1585
  }
1566
1586
  return componentNode;
1567
1587
  }
1568
- insertAfterAnchor(name = 'anchor') {
1588
+ insertAnchor(name = 'anchor', isBefore = false) {
1569
1589
  const _this$ctx = this.ctx,
1570
1590
  realParent = _this$ctx.realParent,
1571
1591
  prevSibling = _this$ctx.prevSibling,
1572
1592
  stack = _this$ctx.stack,
1573
1593
  before = _this$ctx.before;
1574
- const afterAnchor = this.createAnchor(name);
1594
+ const afterAnchor = this.createAnchor(name, isBefore);
1575
1595
  this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
1576
1596
  this.handleInsert(realParent, afterAnchor, prevSibling);
1577
1597
  return afterAnchor;
@@ -1625,7 +1645,7 @@
1625
1645
  _node = this.componentOrFragmentDeclaration(value, ctx);
1626
1646
  } else {
1627
1647
  _node = this.createNode('text');
1628
- _node.text = String(value);
1648
+ this.setProp(_node, 'text', String(value));
1629
1649
  }
1630
1650
  } else {
1631
1651
  return this.dynamicDeclaration(data, value, ctx);
@@ -1655,11 +1675,11 @@
1655
1675
  effect: null,
1656
1676
  textNode: null,
1657
1677
  owner: ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node,
1658
- snapshot: this.tokenizer.snapshot(['dentStack']),
1678
+ snapshot: this.tokenizer.snapshot(['dentStack', 'isFirstToken']),
1659
1679
  parentDataProvider: ctx.stack.peekByType(NodeSort.CtxProvider)?.node
1660
1680
  };
1661
1681
  let isUpdate = false;
1662
- node.realAfter = this.insertAfterAnchor(`dynamic-after`);
1682
+ node.realAfter = this.insertAnchor(`dynamic-after`);
1663
1683
  node.effect = this.effect(({
1664
1684
  old,
1665
1685
  val
@@ -1668,7 +1688,7 @@
1668
1688
  oldTextNode = node.textNode;
1669
1689
  if (oldLogicType) {
1670
1690
  this.removeLogicNode(node);
1671
- bobeShared.pickInPlace(node, ['realParent', 'realBefore', 'realAfter',, 'owner', 'snapshot', 'parentDataProvider']);
1691
+ bobeShared.pickInPlace(node, ['realParent', 'realBefore', 'realAfter', 'owner', 'snapshot', 'parentDataProvider']);
1672
1692
  }
1673
1693
  if (isRenderAble(val)) {
1674
1694
  if (oldTextNode) {
@@ -1695,11 +1715,13 @@
1695
1715
  this.tokenizer = node.tokenizer;
1696
1716
  if (node.fragmentSnapshot) {
1697
1717
  this.tokenizer.resume(node.fragmentSnapshot);
1698
- this.tokenizer.useDedentAsEof = true;
1699
- this.tokenizer.initIndentWhenUseDedentAsEof();
1700
1718
  }
1701
1719
  if (isUpdate) {
1702
- this.program(node.realParent, node.owner, node.realBefore, node);
1720
+ this.tokenizer.useDedentAsEof = false;
1721
+ this.program(node.realParent, node, node.realBefore);
1722
+ } else {
1723
+ this.tokenizer.useDedentAsEof = true;
1724
+ this.tokenizer.initIndentWhenUseDedentAsEof();
1703
1725
  }
1704
1726
  } else {
1705
1727
  node.__logicType = FakeType.DynamicText;
@@ -1708,7 +1730,7 @@
1708
1730
  if (isNewTextNode) {
1709
1731
  textNode = node.textNode = this.createNode('text');
1710
1732
  }
1711
- textNode.text = String(val);
1733
+ this.setProp(textNode, 'text', String(val));
1712
1734
  if (isNewTextNode) {
1713
1735
  if (isUpdate) {
1714
1736
  this.handleInsert(node.realParent, textNode, node.realBefore);
@@ -1720,6 +1742,7 @@
1720
1742
  prevSibling = _this$ctx2.prevSibling;
1721
1743
  this.handleInsert(realParent, textNode, prevSibling);
1722
1744
  }
1745
+ this.leaveNode?.(textNode, false);
1723
1746
  }
1724
1747
  }
1725
1748
  isUpdate = true;
@@ -1750,7 +1773,7 @@
1750
1773
  realBefore: null,
1751
1774
  realAfter: null
1752
1775
  };
1753
- node.realAfter = this.insertAfterAnchor('context-after');
1776
+ node.realAfter = this.insertAnchor('context-after');
1754
1777
  return node;
1755
1778
  }
1756
1779
  formatForCollection(collection) {
@@ -1840,7 +1863,8 @@
1840
1863
  i: 0
1841
1864
  };
1842
1865
  if (keyExp) {
1843
- forNode.getKey = new Function('data', `let v;with(data){v=${keyExp}\n};return v;`);
1866
+ const rawGetKey = new Function('data', `with(data){return (${keyExp})}`);
1867
+ forNode.getKey = data => rawGetKey(safe(data));
1844
1868
  }
1845
1869
  window['for1'] = forNode;
1846
1870
  const data = this.getData();
@@ -1848,7 +1872,7 @@
1848
1872
  const hasArrExpKey = Reflect.has(data[aoye.Keys.Raw], arrExp);
1849
1873
  const arrSignal = hasArrExpKey ? (data[arrExp], cells.get(arrExp)) : new aoye.Computed(this.getFn(data, arrExp));
1850
1874
  forNode.arrSignal = arrSignal;
1851
- forNode.realAfter = this.insertAfterAnchor('for-after');
1875
+ forNode.realAfter = this.insertAnchor('for-after');
1852
1876
  const _forNode$snapshot = forNode.snapshot;
1853
1877
  _forNode$snapshot.dentStack;
1854
1878
  _forNode$snapshot.isFirstToken;
@@ -1871,8 +1895,8 @@
1871
1895
  const len = arr.length;
1872
1896
  for (let i = len; i--;) {
1873
1897
  const item = this.createForItem(forNode, i, data);
1874
- item.realAfter = this.insertAfterAnchor('for-item-after');
1875
- item.realBefore = this.insertAfterAnchor('for-item-before');
1898
+ item.realAfter = this.insertAnchor('for-item-after');
1899
+ item.realBefore = this.insertAnchor('for-item-before', true);
1876
1900
  item.realParent = forNode.realParent;
1877
1901
  children[i] = item;
1878
1902
  }
@@ -2039,7 +2063,7 @@
2039
2063
  newChildren[i] = item;
2040
2064
  let realAfter = this.createAnchor('for-item-after');
2041
2065
  this.handleInsert(forNode.realParent, realAfter, before);
2042
- let realBefore = this.createAnchor('for-item-before');
2066
+ let realBefore = this.createAnchor('for-item-before', true);
2043
2067
  this.handleInsert(forNode.realParent, realBefore, before);
2044
2068
  item.realBefore = realBefore;
2045
2069
  item.realAfter = realAfter;
@@ -2208,11 +2232,11 @@
2208
2232
  resumeSnapshot
2209
2233
  };
2210
2234
  this.onePropParsed = onePropParsed;
2211
- node.realAfter = this.insertAfterAnchor('component-after');
2235
+ node.realAfter = this.insertAnchor('component-after');
2212
2236
  return node;
2213
2237
  }
2214
2238
  getFn(data, expression) {
2215
- return new Function('data', `let v;with(data){v=${expression}};return v;`).bind(undefined, data);
2239
+ return new Function('data', `with(data){return (${expression})}`).bind(undefined, safe(data));
2216
2240
  }
2217
2241
  getAssignFn(data, expression) {
2218
2242
  const valueId = `value_bobe_${bobeShared.date32()}`;
@@ -2303,7 +2327,7 @@
2303
2327
  break;
2304
2328
  }
2305
2329
  ifNode.condition = signal;
2306
- ifNode.realAfter = this.insertAfterAnchor(`${keyWord.value}-after`);
2330
+ ifNode.realAfter = this.insertAnchor(`${keyWord.value}-after`);
2307
2331
  const ef = this.effect(({
2308
2332
  val
2309
2333
  }) => {
@@ -2488,10 +2512,11 @@
2488
2512
  firstChild(node) {
2489
2513
  return node.firstChild;
2490
2514
  }
2491
- createAnchor(name) {
2515
+ createAnchor(name, isBefore) {
2492
2516
  return {
2493
2517
  name,
2494
- nextSibling: null
2518
+ nextSibling: null,
2519
+ isBefore
2495
2520
  };
2496
2521
  }
2497
2522
  insertAfter(parent, node, prev) {
@@ -2561,6 +2586,7 @@
2561
2586
  return tokenizer;
2562
2587
  };
2563
2588
  ui.boundStore = aoye.Store.Current;
2589
+ ui[aoye.Keys.ProxyFreeObject] = true;
2564
2590
  ui.__BOBE_IS_UI = true;
2565
2591
  return ui;
2566
2592
  }
@@ -2577,6 +2603,7 @@
2577
2603
  tokenizer
2578
2604
  };
2579
2605
  terp.program(root, componentNode);
2606
+ option.onBeforeFlush?.();
2580
2607
  aoye.flushMicroEffectManual();
2581
2608
  return [componentNode, store];
2582
2609
  };