bobe 0.0.11 → 0.0.12

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.umd.js CHANGED
@@ -23,13 +23,94 @@
23
23
  LogicType2[LogicType2["Component"] = 16] = "Component";
24
24
  LogicType2[LogicType2["Fragment"] = 32] = "Fragment";
25
25
  LogicType2[LogicType2["Root"] = 64] = "Root";
26
+ LogicType2[LogicType2["Real"] = 128] = "Real";
26
27
  return LogicType2;
27
28
  })(LogicType || {});
29
+ const Logical = 1 /* If */ | 2 /* ElseIf */ | 4 /* Else */ | 8 /* For */;
30
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
31
+ NodeType2[NodeType2["Logic"] = Logical] = "Logic";
32
+ NodeType2[NodeType2["Real"] = 128 /* Real */] = "Real";
33
+ NodeType2[NodeType2["Component"] = 16 /* Component */] = "Component";
34
+ return NodeType2;
35
+ })(NodeType || {});
28
36
  var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
29
37
  TerpEvt2["AllAttrGot"] = "all-attr-got";
30
38
  TerpEvt2["HandledComponentNode"] = "handled-component-node";
31
39
  return TerpEvt2;
32
40
  })(TerpEvt || {});
41
+ const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
42
+
43
+ class TypedStack {
44
+ constructor() {
45
+ this.top = null;
46
+ // 存储每种类型最近一次出现的包装单元引用
47
+ // 使用 Record 来动态支持不同的类型标签
48
+ this.lastNodes = {};
49
+ this.length = 0;
50
+ }
51
+ /**
52
+ * @param rawNode 原始节点数据
53
+ * @param type 节点类型
54
+ */
55
+ push(rawNode, type) {
56
+ var _a;
57
+ const newNode = {
58
+ data: rawNode,
59
+ type,
60
+ prev: this.top,
61
+ prevSameType: (_a = this.lastNodes[type]) != null ? _a : null
62
+ };
63
+ this.top = newNode;
64
+ this.length++;
65
+ this.lastNodes[type] = newNode;
66
+ }
67
+ /**
68
+ * 出栈操作
69
+ * @returns 原始节点数据或 null
70
+ */
71
+ pop() {
72
+ if (!this.top) return null;
73
+ const popped = this.top;
74
+ this.lastNodes[popped.type] = popped.prevSameType;
75
+ this.top = popped.prev;
76
+ this.length--;
77
+ return popped.data;
78
+ }
79
+ /**
80
+ * O(1) 获取栈顶节点的前一个同类型节点
81
+ */
82
+ getPrevSameType() {
83
+ if (!this.top || !this.top.prevSameType) {
84
+ return null;
85
+ }
86
+ return this.top.prevSameType.data;
87
+ }
88
+ findPrevSameType(cb) {
89
+ if (!this.top) {
90
+ return null;
91
+ }
92
+ let point = this.top.prevSameType;
93
+ while (point) {
94
+ if (cb(point.data)) {
95
+ return point.data;
96
+ }
97
+ point = point.prevSameType;
98
+ }
99
+ return null;
100
+ }
101
+ /**
102
+ * 获取当前栈顶的类型
103
+ */
104
+ get peekType() {
105
+ return this.top ? this.top.type : null;
106
+ }
107
+ /**
108
+ * 获取栈顶元素
109
+ */
110
+ peek() {
111
+ return this.top.data;
112
+ }
113
+ }
33
114
 
34
115
  var __defProp$1 = Object.defineProperty;
35
116
  var __defProps$1 = Object.defineProperties;
@@ -79,61 +160,94 @@
79
160
  return [hookType, value];
80
161
  };
81
162
  }
82
- // /** program 要挂载的父节点位置 */
83
- // root: any;
84
- // /** program 挂载的前置节点 */
85
- // anchor: any;
163
+ isLogicNode(node) {
164
+ return node && node.__logicType & Logical;
165
+ }
86
166
  program(root, before) {
167
+ var _a;
87
168
  const componentNode = {
88
169
  __logicType: LogicType.Component,
89
170
  realParent: root,
90
171
  store: new aoye.Store()
91
172
  };
92
173
  this.tokenizer.consume();
93
- let prevSibling = null;
94
- let current;
95
- const stack = [{ node: root, prev: prevSibling }];
174
+ const stack = new TypedStack();
175
+ stack.push({ node: root, prev: null }, NodeType.Real);
176
+ const ctx = {
177
+ realParent: root,
178
+ prevSibling: before,
179
+ current: null,
180
+ stack,
181
+ before
182
+ };
183
+ const rootPulling = aoye.getPulling();
96
184
  while (1) {
97
185
  if (this.tokenizer.isEof()) {
98
- this.handleInsert(root, current, prevSibling, componentNode);
186
+ if (!ctx.prevSibling) ctx.prevSibling = before;
187
+ this.handleInsert(root, ctx.current, ctx.prevSibling, componentNode);
99
188
  break;
100
189
  }
101
190
  const token = this.tokenizer.token;
102
191
  if (token.type & TokenType.Indent) {
103
192
  this.tokenizer.consume();
104
- stack.push({
105
- node: current,
106
- prev: prevSibling
107
- });
108
- current = this.declaration({ stack, prevSibling });
109
- prevSibling = null;
193
+ const isLogicNode = this.isLogicNode(ctx.current);
194
+ stack.push(
195
+ {
196
+ node: ctx.current,
197
+ prev: ctx.prevSibling
198
+ },
199
+ ctx.current.__logicType ? isLogicNode ? NodeType.Logic : NodeType.Component : NodeType.Real
200
+ );
201
+ if (ctx.current.__logicType) {
202
+ if (isLogicNode) {
203
+ aoye.setPulling(ctx.current.effect.ins);
204
+ }
205
+ } else {
206
+ ctx.realParent = ctx.current;
207
+ ctx.prevSibling = null;
208
+ }
209
+ ctx.current = this.declaration(ctx);
110
210
  continue;
111
211
  }
112
- if (current) {
113
- if (stack.length > 1) {
114
- const { node: parent } = stack[stack.length - 1];
115
- this.handleInsert(parent, current, prevSibling);
116
- } else {
117
- if (!prevSibling) {
118
- prevSibling = before;
119
- }
120
- this.handleInsert(root, current, prevSibling, componentNode);
212
+ if (ctx.current) {
213
+ if (stack.length === 1 && !ctx.prevSibling) {
214
+ ctx.prevSibling = before;
121
215
  }
216
+ this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
122
217
  }
123
218
  if (this.tokenizer.token.type & TokenType.Dedent) {
124
219
  this.tokenizer.consume();
125
- const { node: parent, prev } = stack.pop();
126
- prevSibling = prev;
127
- current = parent;
220
+ const { node: parent, prev } = stack.peek();
221
+ if (!parent.__logicType) {
222
+ const prevSameType = stack.getPrevSameType();
223
+ ctx.realParent = prevSameType == null ? void 0 : prevSameType.node;
224
+ } else {
225
+ if (this.isLogicNode(parent)) {
226
+ const parentLogic = (_a = stack.getPrevSameType()) == null ? void 0 : _a.node;
227
+ if (parentLogic) {
228
+ aoye.setPulling(parentLogic.effect.ins);
229
+ } else {
230
+ aoye.setPulling(rootPulling);
231
+ }
232
+ }
233
+ }
234
+ stack.pop();
235
+ ctx.prevSibling = prev;
236
+ ctx.current = parent;
128
237
  } else {
129
- prevSibling = current;
130
- current = this.declaration({ stack, prevSibling });
238
+ ctx.prevSibling = ctx.current || ctx.prevSibling;
239
+ ctx.current = this.declaration(ctx);
131
240
  }
132
241
  }
133
- componentNode.lastInserted = this.lastInserted;
134
- this.lastInserted = null;
135
242
  return componentNode;
136
243
  }
244
+ insertAfterAnchor(ctx) {
245
+ const { realParent, prevSibling, stack, before } = ctx;
246
+ const afterAnchor = this.createAnchor();
247
+ ctx.prevSibling = stack.length === 1 && !prevSibling ? before : prevSibling;
248
+ this.handleInsert(realParent, afterAnchor, prevSibling);
249
+ return afterAnchor;
250
+ }
137
251
  /** 处理
138
252
  * 是逻辑 是普通
139
253
  * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
@@ -145,25 +259,14 @@
145
259
  if (!prev || !prev.__logicType) {
146
260
  this.insertAfter(parent, child, prev);
147
261
  } else {
148
- const before = prev.lastInserted;
262
+ const before = prev.realAfter;
149
263
  this.insertAfter(parent, child, before);
150
- prev.realAfter = child;
151
264
  }
152
265
  } else {
153
266
  const childCmp = child;
154
267
  childCmp.realParent = parent;
155
- if (!prev) {
156
- const anchor = this.createAnchor();
157
- this.insertAfter(parent, anchor, prev);
158
- this.insertAfter(parent, child, anchor);
159
- childCmp.realBefore = anchor;
160
- } else if (prev.__logicType) {
161
- const before = prev.lastInserted;
162
- const anchor = this.createAnchor();
163
- this.insertAfter(parent, anchor, before);
164
- this.insertAfter(parent, child, anchor);
165
- childCmp.realBefore = anchor;
166
- prev.realAfter = anchor;
268
+ if (prev.__logicType) {
269
+ childCmp.realBefore = prev.realAfter;
167
270
  } else {
168
271
  childCmp.realBefore = prev;
169
272
  }
@@ -191,7 +294,7 @@
191
294
  const [hookType, value] = this._hook({});
192
295
  let _node;
193
296
  if (value === "if") {
194
- return this.ifDeclaration();
297
+ return this.ifDeclaration(ctx);
195
298
  } else if (hookType) {
196
299
  if (hookType === "static") {
197
300
  if (typeof value === "function" && value.prototype instanceof aoye.Store) {
@@ -265,37 +368,66 @@
265
368
  child[aoye.Keys.Raw][key] = value;
266
369
  }
267
370
  };
371
+ const afterAnchor = this.insertAfterAnchor(ctx);
268
372
  tap.once(TerpEvt.AllAttrGot, () => {
269
- const parent = ctx.stack[ctx.stack.length - 1].node;
373
+ const parent = ctx.realParent;
270
374
  const prev = ctx.prevSibling;
271
375
  this.onePropParsed = prevOnePropParsed;
272
376
  const componentNode = child["ui"](this.opt, { data: child }, parent, prev);
377
+ componentNode.realAfter = afterAnchor;
273
378
  tap.emit(TerpEvt.HandledComponentNode, componentNode);
274
379
  });
275
380
  return { __logicType: LogicType.Component };
276
381
  }
277
- ifDeclaration() {
382
+ ifDeclaration(ctx) {
278
383
  this.tokenizer.consume();
279
- const [isHook, value] = this._hook({});
384
+ const [hookType, value] = this._hook({});
280
385
  const ifNode = {
281
386
  __logicType: LogicType.If,
282
- condition: value,
283
- realParent: null,
284
387
  snapshot: this.tokenizer.snapshot(),
388
+ condition: null,
389
+ realParent: null,
285
390
  isFirstRender: true,
286
- watcher: null,
287
- anchor: null
391
+ effect: null
288
392
  };
289
- ifNode.watcher = aoye.effect(
393
+ const valueIsMapKey = Reflect.has(this.data[aoye.Keys.Raw], value);
394
+ let signal;
395
+ if (valueIsMapKey) {
396
+ aoye.runWithPulling(() => this.data[value], null);
397
+ const { cells } = this.data[aoye.Keys.Meta];
398
+ signal = cells.get(value);
399
+ } else {
400
+ const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
401
+ signal = aoye.$(fn);
402
+ }
403
+ ifNode.condition = signal;
404
+ ifNode.realAfter = this.insertAfterAnchor(ctx);
405
+ ifNode.effect = aoye.effect(
290
406
  ({ val }) => {
291
407
  if (val) {
292
- this.tokenizer.consume();
293
- this.tokenizer.consume();
408
+ if (ifNode.isFirstRender) {
409
+ this.tokenizer.consume();
410
+ this.tokenizer.consume();
411
+ } else {
412
+ this.tokenizer.resume(ifNode.snapshot);
413
+ this.program(ifNode.realParent, ifNode.realBefore);
414
+ }
294
415
  } else {
295
- this.tokenizer.skip();
416
+ if (ifNode.isFirstRender) {
417
+ this.tokenizer.skip();
418
+ } else {
419
+ const { realBefore, realAfter, realParent } = ifNode;
420
+ let point = this.nextSib(realBefore);
421
+ while (point !== realAfter) {
422
+ const next = this.nextSib(point);
423
+ this.remove(point, realParent, realBefore);
424
+ point = next;
425
+ }
426
+ }
296
427
  }
428
+ ifNode.isFirstRender = false;
297
429
  },
298
- [value]
430
+ [signal]
299
431
  );
300
432
  return ifNode;
301
433
  }
@@ -373,6 +505,11 @@
373
505
  nextSib(node) {
374
506
  return node.nextSibling;
375
507
  }
508
+ _createAnchor() {
509
+ const anchor = this.createAnchor();
510
+ anchor[IsAnchor] = true;
511
+ return anchor;
512
+ }
376
513
  createAnchor() {
377
514
  return {
378
515
  name: "anchor",
@@ -380,7 +517,6 @@
380
517
  };
381
518
  }
382
519
  insertAfter(parent, node, prev) {
383
- this.lastInserted = node;
384
520
  return this.defaultInsert(parent, node, prev);
385
521
  }
386
522
  defaultInsert(parent, node, prev) {
@@ -392,11 +528,11 @@
392
528
  parent.firstChild = node;
393
529
  }
394
530
  }
395
- remove(parent, node, prevSibling) {
396
- return this.defaultRemove(parent, node, prevSibling);
531
+ remove(node, parent, prev) {
532
+ return this.defaultRemove(node, parent, prev);
397
533
  }
398
534
  // TODO: 默认改成 prevItem
399
- defaultRemove(parent, node, prevSibling) {
535
+ defaultRemove(node, parent, prevSibling) {
400
536
  const next = node.nextSibling;
401
537
  if (prevSibling) {
402
538
  prevSibling.nextSibling = next;
@@ -469,7 +605,7 @@
469
605
  };
470
606
  }
471
607
  skip() {
472
- const dentLen = this.dentStack[this.dentStack.length - 1];
608
+ const logicDentLen = this.dentStack[this.dentStack.length - 1];
473
609
  let needIndent = false;
474
610
  let skipFragment = ``;
475
611
  this.token = void 0;
@@ -490,7 +626,7 @@
490
626
  const { value, isEmptyLine } = this.getDentValue();
491
627
  const currLen = value.length;
492
628
  if (isEmptyLine) continue;
493
- if (value.length > dentLen) {
629
+ if (currLen > logicDentLen) {
494
630
  skipFragment += value;
495
631
  } else {
496
632
  for (let i = this.dentStack.length - 1; i >= 0; i--) {
@@ -499,6 +635,9 @@
499
635
  if (currLen > expLen) {
500
636
  throw SyntaxError(`\u7F29\u8FDB\u9519\u8BEF\uFF0C\u7F29\u8FDB\u957F\u5EA6\u4E0D\u5339\u914D`);
501
637
  }
638
+ if (this.shorterThanBaseDentEof()) {
639
+ break;
640
+ }
502
641
  this.dentStack.pop();
503
642
  if (!this.token) {
504
643
  this.setToken(TokenType.Dedent, String(expLen));
@@ -763,12 +902,15 @@ ${_Tokenizer.EofId}`;
763
902
  return indentHasLen;
764
903
  }
765
904
  if (currLen < prevLen) {
766
- for (let i = this.dentStack.length - 2; i >= 0; i--) {
905
+ for (let i = this.dentStack.length; i--; ) {
767
906
  const expLen = this.dentStack[i];
768
- const prevExpLen = this.dentStack[i + 1];
769
- if (currLen > expLen && currLen < prevExpLen) {
907
+ if (currLen === expLen) break;
908
+ if (currLen > expLen) {
770
909
  throw SyntaxError("\u7F29\u8FDB\u5927\u5C0F\u4E0D\u7EDF\u4E00");
771
910
  }
911
+ if (this.shorterThanBaseDentEof()) {
912
+ return;
913
+ }
772
914
  this.dentStack.pop();
773
915
  if (!this.token) {
774
916
  this.setToken(TokenType.Dedent, String(expLen));
@@ -779,14 +921,26 @@ ${_Tokenizer.EofId}`;
779
921
  value: String(expLen)
780
922
  });
781
923
  }
782
- if (currLen === expLen) {
783
- break;
784
- }
785
924
  }
786
925
  return indentHasLen;
787
926
  }
788
927
  return indentHasLen;
789
928
  }
929
+ shorterThanBaseDentEof() {
930
+ const yes = this.dentStack.length === 1;
931
+ if (yes) {
932
+ if (!this.token) {
933
+ this.setToken(TokenType.Identifier, _Tokenizer.EofId);
934
+ } else {
935
+ this.waitingTokens.push({
936
+ type: TokenType.Identifier,
937
+ typeName: TokenType[TokenType.Identifier],
938
+ value: _Tokenizer.EofId
939
+ });
940
+ }
941
+ }
942
+ return yes;
943
+ }
790
944
  identifier(char) {
791
945
  let value = char;
792
946
  let nextC;