bobe 0.0.15 → 0.0.16

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
@@ -1,4 +1,4 @@
1
- import { Store, getPulling, setPulling, Keys, effect, shareSignal, $, runWithPulling } from 'aoye';
1
+ import { getPulling, setPulling, Store, Keys, effect, shareSignal, $, runWithPulling } from 'aoye';
2
2
  export * from 'aoye';
3
3
  import { BaseEvent, Queue, isNum } from 'bobe-shared';
4
4
 
@@ -13,25 +13,27 @@ var TokenType = /* @__PURE__ */ ((TokenType2) => {
13
13
  TokenType2[TokenType2["InsertionExp"] = 128] = "InsertionExp";
14
14
  return TokenType2;
15
15
  })(TokenType || {});
16
- var LogicType = /* @__PURE__ */ ((LogicType2) => {
17
- LogicType2[LogicType2["If"] = 1] = "If";
18
- LogicType2[LogicType2["Fail"] = 2] = "Fail";
19
- LogicType2[LogicType2["Else"] = 4] = "Else";
20
- LogicType2[LogicType2["For"] = 8] = "For";
21
- LogicType2[LogicType2["Component"] = 16] = "Component";
22
- LogicType2[LogicType2["Fragment"] = 32] = "Fragment";
23
- LogicType2[LogicType2["Root"] = 64] = "Root";
24
- LogicType2[LogicType2["Real"] = 128] = "Real";
25
- return LogicType2;
26
- })(LogicType || {});
27
- const Logical = 1 /* If */ | 2 /* Fail */ | 4 /* Else */ | 8 /* For */;
28
- const CondType = 1 /* If */ | 2 /* Fail */ | 4 /* Else */;
29
- var NodeType = /* @__PURE__ */ ((NodeType2) => {
30
- NodeType2[NodeType2["Logic"] = Logical] = "Logic";
31
- NodeType2[NodeType2["Real"] = 128 /* Real */] = "Real";
32
- NodeType2[NodeType2["Component"] = 16 /* Component */] = "Component";
33
- return NodeType2;
34
- })(NodeType || {});
16
+ var FakeType = /* @__PURE__ */ ((FakeType2) => {
17
+ FakeType2[FakeType2["If"] = 1] = "If";
18
+ FakeType2[FakeType2["Fail"] = 2] = "Fail";
19
+ FakeType2[FakeType2["Else"] = 4] = "Else";
20
+ FakeType2[FakeType2["For"] = 8] = "For";
21
+ FakeType2[FakeType2["Component"] = 16] = "Component";
22
+ FakeType2[FakeType2["Fragment"] = 32] = "Fragment";
23
+ FakeType2[FakeType2["ForItem"] = 64] = "ForItem";
24
+ return FakeType2;
25
+ })(FakeType || {});
26
+ const CondBit = 1 /* If */ | 2 /* Fail */ | 4 /* Else */;
27
+ const LogicalBit = 1 /* If */ | 2 /* Fail */ | 4 /* Else */ | 8 /* For */ | 64 /* ForItem */;
28
+ const TokenizerSwitcherBit = 16 /* Component */ | 32 /* Fragment */;
29
+ var NodeSort = /* @__PURE__ */ ((NodeSort2) => {
30
+ NodeSort2[NodeSort2["Logic"] = 1] = "Logic";
31
+ NodeSort2[NodeSort2["Real"] = 2] = "Real";
32
+ NodeSort2[NodeSort2["Component"] = 4] = "Component";
33
+ NodeSort2[NodeSort2["CtxProvider"] = 8] = "CtxProvider";
34
+ NodeSort2[NodeSort2["TokenizerSwitcher"] = 16] = "TokenizerSwitcher";
35
+ return NodeSort2;
36
+ })(NodeSort || {});
35
37
  var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
36
38
  TerpEvt2["AllAttrGot"] = "all-attr-got";
37
39
  TerpEvt2["HandledComponentNode"] = "handled-component-node";
@@ -39,140 +41,119 @@ var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
39
41
  })(TerpEvt || {});
40
42
  const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
41
43
 
42
- class TypedStack {
44
+ class MultiTypeStack {
43
45
  constructor() {
46
+ // 记录全局栈顶
44
47
  this.top = null;
45
- // 存储每种类型最近一次出现的包装单元引用
46
- // 使用 Record 来动态支持不同的类型标签
47
- this.lastNodes = {};
48
+ // 记录每个类别的当前最新节点(各分类的“栈顶”)
49
+ this.typeTops = {};
48
50
  this.length = 0;
49
51
  }
50
52
  /**
51
- * @param rawNode 原始节点数据
52
- * @param type 节点类型
53
+ * 入栈操作
54
+ * @param value 数据
55
+ * @param bits 该节点所属的类别数组
53
56
  */
54
- push(rawNode, type) {
55
- var _a;
57
+ push(value, bits) {
56
58
  const newNode = {
57
- data: rawNode,
58
- type,
59
- prev: this.top,
60
- prevSameType: (_a = this.lastNodes[type]) != null ? _a : null
59
+ value,
60
+ types: bits,
61
+ prevGlobal: this.top,
62
+ prevByType: {}
61
63
  };
64
+ let bit;
65
+ while (1) {
66
+ bit = bits & ~bits + 1;
67
+ if (!bit) break;
68
+ bits &= ~bit;
69
+ newNode.prevByType[bit] = this.typeTops[bit] || void 0;
70
+ this.typeTops[bit] = newNode;
71
+ }
62
72
  this.top = newNode;
63
73
  this.length++;
64
- this.lastNodes[type] = newNode;
65
74
  }
66
75
  /**
67
76
  * 出栈操作
68
- * @returns 原始节点数据或 null
69
77
  */
70
78
  pop() {
71
- if (!this.top) return null;
72
- const popped = this.top;
73
- this.lastNodes[popped.type] = popped.prevSameType;
74
- this.top = popped.prev;
79
+ if (!this.top) return void 0;
80
+ const poppedNode = this.top;
81
+ let { types: bits } = poppedNode;
82
+ let bit;
83
+ while (1) {
84
+ bit = bits & ~bits + 1;
85
+ if (!bit) break;
86
+ bits &= ~bit;
87
+ this.typeTops[bit] = poppedNode.prevByType[bit];
88
+ }
89
+ this.top = poppedNode.prevGlobal;
75
90
  this.length--;
76
- return popped.data;
91
+ return [poppedNode.value, poppedNode.types];
77
92
  }
78
93
  /**
79
- * O(1) 获取栈顶节点的前一个同类型节点
94
+ * 获取某个类别的当前“顶部”元素
80
95
  */
81
- getPrevSameType() {
82
- if (!this.top || !this.top.prevSameType) {
83
- return null;
84
- }
85
- return this.top.prevSameType.data;
96
+ peekByType(cat) {
97
+ var _a;
98
+ return (_a = this.typeTops[cat]) == null ? void 0 : _a.value;
86
99
  }
87
- findPrevSameType(cb) {
88
- if (!this.top) {
89
- return null;
90
- }
91
- let point = this.top.prevSameType;
92
- while (point) {
93
- if (cb(point.data)) {
94
- return point.data;
95
- }
96
- point = point.prevSameType;
97
- }
98
- return null;
100
+ peekType() {
101
+ var _a;
102
+ return (_a = this.top) == null ? void 0 : _a.types;
99
103
  }
100
104
  /**
101
- * 获取当前栈顶的类型
105
+ * 获取全局栈顶
102
106
  */
103
- get peekType() {
104
- return this.top ? this.top.type : null;
107
+ peek() {
108
+ var _a;
109
+ return (_a = this.top) == null ? void 0 : _a.value;
105
110
  }
106
111
  /**
107
- * 获取栈顶元素
112
+ * 1. 全局向前遍历 (不分类)
113
+ * 从栈顶开始,沿着全局链条向栈底遍历
108
114
  */
109
- peek() {
110
- return this.top.data;
115
+ forEach(callback) {
116
+ let current = this.top;
117
+ while (current !== null) {
118
+ const shouldBreak = callback(current.value, current.types);
119
+ if (shouldBreak) break;
120
+ current = current.prevGlobal;
121
+ }
122
+ }
123
+ /**
124
+ * 2. 按类别向前遍历
125
+ * 仅遍历属于指定类别 cat 的节点
126
+ */
127
+ forEachByType(cat, callback) {
128
+ let current = this.typeTops[cat];
129
+ while (current) {
130
+ const shouldBreak = callback(current.value);
131
+ if (shouldBreak) break;
132
+ current = current.prevByType[cat];
133
+ }
111
134
  }
112
135
  }
113
136
 
114
- var __defProp$1 = Object.defineProperty;
115
- var __defProps$1 = Object.defineProperties;
116
- var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
117
- var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
118
- var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
119
- var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
120
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
121
- var __spreadValues$1 = (a, b) => {
122
- for (var prop in b || (b = {}))
123
- if (__hasOwnProp$1.call(b, prop))
124
- __defNormalProp$1(a, prop, b[prop]);
125
- if (__getOwnPropSymbols$1)
126
- for (var prop of __getOwnPropSymbols$1(b)) {
127
- if (__propIsEnum$1.call(b, prop))
128
- __defNormalProp$1(a, prop, b[prop]);
129
- }
130
- return a;
131
- };
132
- var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
133
137
  const tap = new BaseEvent();
134
138
  class Interpreter {
135
139
  constructor(tokenizer) {
136
140
  this.tokenizer = tokenizer;
137
- /** 模板字符串动态节点的占位符 */
138
- this.HookId = "_h_o_o_k_";
139
- /** 用于渲染的数据 */
140
- this.data = {};
141
- /** 模板字符串动态节点索引 */
142
- this.hookI = 0;
143
- this._hook = (props) => {
144
- const value = this.tokenizer.token.value;
145
- const isDynamicHook = this.tokenizer.token.type & TokenType.InsertionExp;
146
- const isStaticHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
147
- const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
148
- if (this.hook && isStaticHook) {
149
- const hookI = Number(value.slice(this.HookId.length));
150
- const res = this.hook(__spreadProps$1(__spreadValues$1({}, props), {
151
- HookId: this.HookId,
152
- i: hookI
153
- }));
154
- this.hookI++;
155
- return [hookType, res];
156
- } else if (isDynamicHook) {
157
- return [hookType, value];
158
- }
159
- return [hookType, value];
160
- };
141
+ this.rootComponent = null;
161
142
  }
162
143
  isLogicNode(node) {
163
- return node && node.__logicType & Logical;
144
+ return node && node.__logicType & LogicalBit;
164
145
  }
165
- program(root, before) {
166
- var _a;
167
- const componentNode = {
168
- __logicType: LogicType.Component,
169
- realParent: root,
170
- store: new Store()
171
- };
146
+ program(root, componentNode, before) {
147
+ var _a, _b;
148
+ this.rootComponent = componentNode;
172
149
  this.tokenizer.consume();
173
- const stack = new TypedStack();
174
- stack.push({ node: root, prev: null }, NodeType.Real);
175
- const ctx = {
150
+ const stack = new MultiTypeStack();
151
+ stack.push({ node: root, prev: null }, NodeSort.Real);
152
+ stack.push(
153
+ { node: componentNode, prev: null },
154
+ NodeSort.Component | NodeSort.CtxProvider | NodeSort.TokenizerSwitcher
155
+ );
156
+ const ctx = this.ctx = {
176
157
  realParent: root,
177
158
  prevSibling: before,
178
159
  current: null,
@@ -195,7 +176,7 @@ class Interpreter {
195
176
  node: ctx.current,
196
177
  prev: ctx.prevSibling
197
178
  },
198
- ctx.current.__logicType ? isLogicNode ? NodeType.Logic : NodeType.Component : NodeType.Real
179
+ !ctx.current.__logicType ? NodeSort.Real : (ctx.current.__logicType & LogicalBit ? NodeSort.Logic : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | NodeSort.CtxProvider
199
180
  );
200
181
  if (ctx.current.__logicType) {
201
182
  if (isLogicNode) {
@@ -211,28 +192,31 @@ class Interpreter {
211
192
  continue;
212
193
  }
213
194
  if (ctx.current) {
214
- if (stack.length === 1 && !ctx.prevSibling) {
195
+ if (stack.length === 2 && !ctx.prevSibling) {
215
196
  ctx.prevSibling = before;
216
197
  }
217
198
  this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
218
199
  }
219
200
  if (this.tokenizer.token.type & TokenType.Dedent) {
220
201
  this.tokenizer.consume();
221
- const { node: parent, prev } = stack.peek();
202
+ const [{ node: parent, prev }, sort] = stack.pop();
222
203
  if (!parent.__logicType) {
223
- const prevSameType = stack.getPrevSameType();
204
+ const prevSameType = stack.peekByType(NodeSort.Real);
224
205
  ctx.realParent = (prevSameType == null ? void 0 : prevSameType.node) || root;
225
206
  } else {
226
- if (this.isLogicNode(parent)) {
227
- const parentLogic = (_a = stack.getPrevSameType()) == null ? void 0 : _a.node;
207
+ if (sort & NodeSort.Logic) {
208
+ const parentLogic = (_a = stack.peekByType(NodeSort.Logic)) == null ? void 0 : _a.node;
228
209
  if (parentLogic) {
229
210
  setPulling(parentLogic.effect.ins);
230
211
  } else {
231
212
  setPulling(rootPulling);
232
213
  }
233
214
  }
215
+ if (sort & NodeSort.TokenizerSwitcher) {
216
+ const switcher = (_b = stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _b.node;
217
+ this.tokenizer = switcher.tokenizer;
218
+ }
234
219
  }
235
- stack.pop();
236
220
  ctx.prevSibling = prev;
237
221
  ctx.current = parent;
238
222
  } else {
@@ -242,10 +226,15 @@ class Interpreter {
242
226
  }
243
227
  return componentNode;
244
228
  }
229
+ switcherIsRootComponent() {
230
+ var _a;
231
+ const currentSwitcher = (_a = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
232
+ return currentSwitcher === this.rootComponent;
233
+ }
245
234
  insertAfterAnchor(ctx) {
246
235
  const { realParent, prevSibling, stack, before } = ctx;
247
236
  const afterAnchor = this.createAnchor();
248
- ctx.prevSibling = stack.length === 1 && !prevSibling ? before : prevSibling;
237
+ ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
249
238
  this.handleInsert(realParent, afterAnchor, prevSibling);
250
239
  return afterAnchor;
251
240
  }
@@ -292,7 +281,7 @@ class Interpreter {
292
281
  * <declaration> ::= <tagName=token> <headerLine> <extensionLines>
293
282
  * */
294
283
  declaration(ctx) {
295
- const [hookType, value] = this._hook({});
284
+ const [hookType, value] = this.tokenizer._hook({});
296
285
  let _node;
297
286
  if (value === "if" || value === "else" || value === "fail") {
298
287
  return this.condDeclaration(ctx);
@@ -301,12 +290,13 @@ class Interpreter {
301
290
  if (typeof value === "function" && value.prototype instanceof Store) {
302
291
  _node = this.componentDeclaration(value, ctx);
303
292
  } else if (typeof value === "function") {
304
- _node = this.fragmentDeclaration(value);
293
+ _node = this.fragmentDeclaration(value, ctx);
305
294
  } else {
306
295
  throw new SyntaxError(`declaration \u4E0D\u652F\u6301 ${value} \u7C7B\u578B\u7684\u9759\u6001\u63D2\u503C`);
307
296
  }
308
297
  } else {
309
- Boolean(this.data[Keys.Raw][value]);
298
+ const data = this.getData();
299
+ Boolean(data[Keys.Raw][value]);
310
300
  new Function("data", `let v;with(data){v=(${value})};return v`);
311
301
  _node = this.createNode(value);
312
302
  }
@@ -316,19 +306,26 @@ class Interpreter {
316
306
  this.tokenizer.consume();
317
307
  this.headerLine(_node);
318
308
  this.extensionLines(_node);
319
- if (_node.__logicType === LogicType.Component) {
309
+ if (_node.__logicType === FakeType.Component) {
320
310
  tap.once(TerpEvt.HandledComponentNode, (node) => _node = node);
321
311
  tap.emit(TerpEvt.AllAttrGot);
322
312
  }
323
313
  return _node;
324
314
  }
315
+ getData() {
316
+ const { node } = this.ctx.stack.peekByType(NodeSort.CtxProvider);
317
+ return node.data || node.owner.data;
318
+ }
325
319
  // TODO: 指定挂载位置
326
- fragmentDeclaration(renderFragment) {
320
+ fragmentDeclaration(renderFragment, ctx) {
321
+ const data = this.getData();
322
+ const tokenizer = renderFragment.call(data, this.opt, { data, root: "", anchor: "" });
327
323
  const fragmentNode = {
328
- __logicType: LogicType.Fragment,
329
- realParent: null
324
+ __logicType: FakeType.Fragment,
325
+ realParent: null,
326
+ tokenizer,
327
+ data: null
330
328
  };
331
- renderFragment.call(this.data, this.opt, { data: this.data, root: "", anchor: "" });
332
329
  return fragmentNode;
333
330
  }
334
331
  /**
@@ -339,15 +336,17 @@ class Interpreter {
339
336
  *
340
337
  * mapKey 映射, 对应子组件的属性
341
338
  * */
342
- onePropParsed(node, key, value, valueIsMapKey, hookI) {
343
- if (typeof value === "function") {
339
+ onePropParsed(data, node, key, value, valueIsMapKey, isFn, hookI) {
340
+ if (isFn) {
341
+ this.setProp(node, key, value, hookI);
342
+ } else if (typeof value === "function") {
344
343
  effect(() => {
345
344
  const res = value();
346
345
  this.setProp(node, key, res, hookI);
347
346
  });
348
347
  } else if (valueIsMapKey) {
349
348
  effect(() => {
350
- const res = this.data[value];
349
+ const res = data[value];
351
350
  this.setProp(node, key, res, hookI);
352
351
  });
353
352
  } else {
@@ -356,10 +355,18 @@ class Interpreter {
356
355
  }
357
356
  componentDeclaration(Component, ctx) {
358
357
  const child = Component.new();
358
+ const componentNode = {
359
+ __logicType: FakeType.Component,
360
+ realParent: ctx.realParent,
361
+ data: child,
362
+ tokenizer: null
363
+ };
359
364
  const prevOnePropParsed = this.onePropParsed;
360
- this.onePropParsed = (node, key, value, valueIsMapKey, hookI) => {
361
- if (valueIsMapKey) {
362
- shareSignal(this.data, value, child, key);
365
+ this.onePropParsed = (data, node, key, value, valueIsMapKey, isFn, hookI) => {
366
+ if (isFn) {
367
+ child[Keys.Raw][key] = value;
368
+ } else if (valueIsMapKey) {
369
+ shareSignal(data, value, child, key);
363
370
  } else if (typeof value === "function") {
364
371
  const meta = child[Keys.Meta];
365
372
  const cells = meta.cells;
@@ -369,37 +376,40 @@ class Interpreter {
369
376
  child[Keys.Raw][key] = value;
370
377
  }
371
378
  };
372
- const afterAnchor = this.insertAfterAnchor(ctx);
379
+ componentNode.realAfter = this.insertAfterAnchor(ctx);
373
380
  const { realParent, prevSibling } = ctx;
374
381
  tap.once(TerpEvt.AllAttrGot, () => {
375
- const parent = realParent;
376
- const prev = prevSibling;
377
382
  this.onePropParsed = prevOnePropParsed;
378
- const componentNode = child["ui"](this.opt, { data: child }, parent, prev);
379
- componentNode.realAfter = afterAnchor;
383
+ const subTkr = child["ui"](true);
384
+ componentNode.tokenizer = subTkr;
385
+ this.tokenizer = subTkr;
380
386
  tap.emit(TerpEvt.HandledComponentNode, componentNode);
381
387
  });
382
- return { __logicType: LogicType.Component };
388
+ return componentNode;
383
389
  }
384
390
  // TODO: 优化代码逻辑,拆分 if elseif else
385
391
  condDeclaration(ctx) {
392
+ var _a;
386
393
  const { prevSibling } = ctx;
387
394
  const snapbackUp = this.tokenizer.snapshot();
388
395
  const keyWord = this.tokenizer.consume();
389
396
  const noSelfCond = this.tokenizer.token.type === TokenType.NewLine;
390
- const [hookType, value] = this._hook({});
397
+ const [hookType, value] = this.tokenizer._hook({});
391
398
  const isElse = keyWord.value === "else";
392
399
  const isIf = keyWord.value === "if";
393
- const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondType;
400
+ const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondBit;
394
401
  const needCalcWithPrevIf = isElse && preIsCond;
402
+ const data = this.getData();
403
+ const owner = (_a = ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
395
404
  const ifNode = {
396
- __logicType: isElse ? LogicType.Else : isIf ? LogicType.If : LogicType.Fail,
405
+ __logicType: isElse ? FakeType.Else : isIf ? FakeType.If : FakeType.Fail,
397
406
  snapshot: noSelfCond ? snapbackUp : this.tokenizer.snapshot(),
398
407
  condition: null,
399
408
  realParent: null,
400
409
  preCond: preIsCond ? prevSibling : null,
401
410
  isFirstRender: true,
402
- effect: null
411
+ effect: null,
412
+ owner
403
413
  };
404
414
  let signal;
405
415
  if (noSelfCond) {
@@ -410,7 +420,7 @@ class Interpreter {
410
420
  if (point.condition.v) {
411
421
  return false;
412
422
  }
413
- if (point.__logicType === LogicType.If) {
423
+ if (point.__logicType === FakeType.If) {
414
424
  break;
415
425
  }
416
426
  point = point.preCond;
@@ -430,13 +440,13 @@ class Interpreter {
430
440
  });
431
441
  }
432
442
  } else {
433
- const valueIsMapKey = Reflect.has(this.data[Keys.Raw], value);
443
+ const valueIsMapKey = Reflect.has(data[Keys.Raw], value);
434
444
  if (valueIsMapKey && !needCalcWithPrevIf) {
435
- runWithPulling(() => this.data[value], null);
436
- const { cells } = this.data[Keys.Meta];
445
+ runWithPulling(() => data[value], null);
446
+ const { cells } = data[Keys.Meta];
437
447
  signal = cells.get(value);
438
448
  } else {
439
- const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
449
+ const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
440
450
  if (needCalcWithPrevIf) {
441
451
  signal = $(() => {
442
452
  let point = ifNode.preCond;
@@ -444,7 +454,7 @@ class Interpreter {
444
454
  if (point.condition.v) {
445
455
  return false;
446
456
  }
447
- if (point.__logicType === LogicType.If) {
457
+ if (point.__logicType === FakeType.If) {
448
458
  break;
449
459
  }
450
460
  point = point.preCond;
@@ -467,8 +477,9 @@ class Interpreter {
467
477
  }
468
478
  this.tokenizer.consume();
469
479
  } else {
480
+ this.tokenizer = ifNode.owner.tokenizer;
470
481
  this.tokenizer.resume(ifNode.snapshot);
471
- this.program(ifNode.realParent, ifNode.realBefore);
482
+ this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore);
472
483
  }
473
484
  } else {
474
485
  if (ifNode.isFirstRender) {
@@ -479,7 +490,7 @@ class Interpreter {
479
490
  this.tokenizer.skip();
480
491
  } else {
481
492
  const { realBefore, realAfter, realParent } = ifNode;
482
- let point = realBefore ? this.nextSib(realBefore) : this.kid(realParent);
493
+ let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
483
494
  while (point !== realAfter) {
484
495
  const next = this.nextSib(point);
485
496
  this.remove(point, realParent, realBefore);
@@ -531,21 +542,24 @@ class Interpreter {
531
542
  */
532
543
  attributeList(_node) {
533
544
  let key, eq;
545
+ const data = this.getData();
534
546
  while (!(this.tokenizer.token.type & TokenType.NewLine)) {
535
547
  if (key == null) {
536
548
  key = this.tokenizer.token.value;
537
549
  } else if (eq == null) {
538
550
  eq = "=";
539
551
  } else {
540
- const [hookType, value] = this._hook({});
552
+ const [hookType, value, hookI] = this.tokenizer._hook({});
553
+ const rawVal = Reflect.get(data[Keys.Raw], value);
554
+ const isFn = typeof rawVal === "function";
541
555
  if (hookType === "dynamic") {
542
- const valueIsMapKey = Reflect.has(this.data[Keys.Raw], value);
543
- const fn = valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
544
- this.onePropParsed(_node, key, fn, valueIsMapKey, this.hookI);
556
+ const valueIsMapKey = Reflect.has(data[Keys.Raw], value);
557
+ const fn = isFn ? rawVal : valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
558
+ this.onePropParsed(data, _node, key, fn, valueIsMapKey, isFn, hookI);
545
559
  } else if (hookType === "static") {
546
- this.onePropParsed(_node, key, value, false, this.hookI);
560
+ this.onePropParsed(data, _node, key, value, false, isFn, hookI);
547
561
  } else {
548
- this.onePropParsed(_node, key, value, false, this.hookI);
562
+ this.onePropParsed(data, _node, key, value, false, isFn, hookI);
549
563
  }
550
564
  key = null;
551
565
  eq = null;
@@ -567,7 +581,7 @@ class Interpreter {
567
581
  nextSib(node) {
568
582
  return node.nextSibling;
569
583
  }
570
- kid(node) {
584
+ firstChild(node) {
571
585
  return node.firstChild;
572
586
  }
573
587
  _createAnchor() {
@@ -611,28 +625,35 @@ class Interpreter {
611
625
  setProp(node, key, value, hookI) {
612
626
  node.props[key] = value;
613
627
  }
614
- init(fragments) {
615
- if (typeof fragments === "string") {
616
- this.tokenizer.setCode(fragments);
617
- } else {
618
- let code = "";
619
- for (let i = 0; i < fragments.length - 1; i++) {
620
- const fragment = fragments[i];
621
- code += fragment + `${this.HookId}${i}`;
622
- }
623
- this.tokenizer.setCode(code + fragments[fragments.length - 1]);
624
- }
625
- }
626
628
  }
627
629
 
630
+ var __defProp = Object.defineProperty;
631
+ var __defProps = Object.defineProperties;
632
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
633
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
634
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
635
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
636
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
637
+ var __spreadValues = (a, b) => {
638
+ for (var prop in b || (b = {}))
639
+ if (__hasOwnProp.call(b, prop))
640
+ __defNormalProp(a, prop, b[prop]);
641
+ if (__getOwnPropSymbols)
642
+ for (var prop of __getOwnPropSymbols(b)) {
643
+ if (__propIsEnum.call(b, prop))
644
+ __defNormalProp(a, prop, b[prop]);
645
+ }
646
+ return a;
647
+ };
648
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
628
649
  const _Tokenizer = class _Tokenizer {
629
- constructor() {
650
+ constructor(hook, isSubToken) {
651
+ this.hook = hook;
652
+ this.isSubToken = isSubToken;
630
653
  /** 缩进大小 默认 2 */
631
654
  this.TabSize = 2;
632
655
  /** 缩进字符 */
633
656
  this.Tab = Array.from({ length: this.TabSize }, () => " ").join("");
634
- /** 匹配标识符 */
635
- this.IdExp = /[\d\w\/]/;
636
657
  /** 回车后需要判断缩进 */
637
658
  this.needIndent = false;
638
659
  /** 用于跳过第一个节点前的空白字符串,以及生成基础缩进 */
@@ -641,6 +662,7 @@ const _Tokenizer = class _Tokenizer {
641
662
  this.dentStack = [0];
642
663
  /** 当前字符 index */
643
664
  this.i = 0;
665
+ // TODO: 生产环境不需要这个,导致不必要的内存占用
644
666
  this.handledTokens = [];
645
667
  /**
646
668
  * 有些标识符能产生多个 token
@@ -651,6 +673,31 @@ const _Tokenizer = class _Tokenizer {
651
673
  * parent2 <- 产生两个 dedent
652
674
  */
653
675
  this.waitingTokens = new Queue();
676
+ /** 模板字符串动态节点的占位符 */
677
+ this.HookId = "_h_o_o_k_";
678
+ /** 模板字符串动态节点索引 */
679
+ this.hookI = 0;
680
+ this._hook = (props) => {
681
+ const value = this.token.value;
682
+ const isDynamicHook = this.token.type & TokenType.InsertionExp;
683
+ const isStaticHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
684
+ const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
685
+ if (this.hook && isStaticHook) {
686
+ const hookI = Number(value.slice(this.HookId.length));
687
+ const res = this.hook(__spreadProps(__spreadValues({}, props), {
688
+ HookId: this.HookId,
689
+ i: hookI
690
+ }));
691
+ return [hookType, res, hookI];
692
+ } else if (isDynamicHook) {
693
+ return [hookType, value];
694
+ }
695
+ return [hookType, value];
696
+ };
697
+ if (isSubToken) {
698
+ this.setToken(TokenType.Indent, "");
699
+ this.isFirstToken = true;
700
+ }
654
701
  }
655
702
  consume() {
656
703
  const token = this.token;
@@ -764,7 +811,7 @@ ${_Tokenizer.EofId}`;
764
811
  }
765
812
  testId(value) {
766
813
  if (typeof value !== "string") return false;
767
- return this.IdExp.test(value);
814
+ return _Tokenizer.IdExp.test(value);
768
815
  }
769
816
  nextToken() {
770
817
  try {
@@ -997,13 +1044,25 @@ ${_Tokenizer.EofId}`;
997
1044
  const yes = this.dentStack.length === 1;
998
1045
  if (yes) {
999
1046
  if (!this.token) {
1000
- this.setToken(TokenType.Identifier, _Tokenizer.EofId);
1047
+ if (this.isSubToken) {
1048
+ this.setToken(TokenType.Dedent, "");
1049
+ } else {
1050
+ this.setToken(TokenType.Identifier, _Tokenizer.EofId);
1051
+ }
1001
1052
  } else {
1002
- this.waitingTokens.push({
1003
- type: TokenType.Identifier,
1004
- typeName: TokenType[TokenType.Identifier],
1005
- value: _Tokenizer.EofId
1006
- });
1053
+ if (this.isSubToken) {
1054
+ this.waitingTokens.push({
1055
+ type: TokenType.Dedent,
1056
+ typeName: TokenType[TokenType.Dedent],
1057
+ value: ""
1058
+ });
1059
+ } else {
1060
+ this.waitingTokens.push({
1061
+ type: TokenType.Identifier,
1062
+ typeName: TokenType[TokenType.Identifier],
1063
+ value: _Tokenizer.EofId
1064
+ });
1065
+ }
1007
1066
  }
1008
1067
  }
1009
1068
  return yes;
@@ -1019,6 +1078,10 @@ ${_Tokenizer.EofId}`;
1019
1078
  value += nextC;
1020
1079
  this.next();
1021
1080
  }
1081
+ if (value === _Tokenizer.EofId && this.isSubToken) {
1082
+ this.setToken(TokenType.Dedent, "");
1083
+ return;
1084
+ }
1022
1085
  let realValue = value === "null" ? null : value === "undefined" ? void 0 : value === "false" ? false : value === "true" ? true : value;
1023
1086
  this.setToken(TokenType.Identifier, realValue);
1024
1087
  }
@@ -1058,52 +1121,50 @@ ${_Tokenizer.EofId}`;
1058
1121
  eof() {
1059
1122
  this.setToken(TokenType.Eof, "End Of File");
1060
1123
  }
1124
+ init(fragments) {
1125
+ if (typeof fragments === "string") {
1126
+ this.setCode(fragments);
1127
+ } else {
1128
+ let code = "";
1129
+ for (let i = 0; i < fragments.length - 1; i++) {
1130
+ const fragment = fragments[i];
1131
+ code += fragment + `${this.HookId}${i}`;
1132
+ }
1133
+ this.setCode(code + fragments[fragments.length - 1]);
1134
+ }
1135
+ }
1061
1136
  };
1137
+ /** 匹配标识符 */
1138
+ _Tokenizer.IdExp = /[\d\w\/]/;
1062
1139
  /** Eof 标识符的值 */
1063
1140
  _Tokenizer.EofId = `__EOF__${Date.now()}`;
1141
+ _Tokenizer.DedentId = `__DEDENT__${Date.now()}`;
1064
1142
  let Tokenizer = _Tokenizer;
1065
1143
 
1066
- var __defProp = Object.defineProperty;
1067
- var __defProps = Object.defineProperties;
1068
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
1069
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
1070
- var __hasOwnProp = Object.prototype.hasOwnProperty;
1071
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
1072
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1073
- var __spreadValues = (a, b) => {
1074
- for (var prop in b || (b = {}))
1075
- if (__hasOwnProp.call(b, prop))
1076
- __defNormalProp(a, prop, b[prop]);
1077
- if (__getOwnPropSymbols)
1078
- for (var prop of __getOwnPropSymbols(b)) {
1079
- if (__propIsEnum.call(b, prop))
1080
- __defNormalProp(a, prop, b[prop]);
1081
- }
1082
- return a;
1083
- };
1084
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1085
1144
  function bobe(fragments, ...values) {
1086
- const ui = function ui2(options, valueOpt, root, before) {
1087
- const tokenizer = new Tokenizer();
1088
- const cmp = new Interpreter(tokenizer);
1089
- Object.assign(cmp, valueOpt);
1090
- cmp.config(__spreadProps(__spreadValues({}, options), {
1091
- hook({ i }) {
1092
- return values[i];
1093
- },
1094
- setProp(node, key, value, hookI) {
1095
- node.props[key] = value;
1096
- }
1097
- }));
1098
- cmp.init(Array.from(fragments));
1099
- return cmp.program(root, before);
1145
+ const ui = function ui2(isSub) {
1146
+ const tokenizer = new Tokenizer(({ i }) => {
1147
+ return values[i];
1148
+ }, isSub);
1149
+ tokenizer.init(Array.from(fragments));
1150
+ return tokenizer;
1100
1151
  };
1101
1152
  return ui;
1102
1153
  }
1103
1154
  function customRender(option) {
1104
1155
  return function render(Ctor, root) {
1105
1156
  const store = Ctor.new();
1106
- return [store["ui"](option, { data: store }, root), store];
1157
+ const tokenizer = store["ui"](false);
1158
+ const terp = new Interpreter(tokenizer);
1159
+ terp.config(option);
1160
+ const componentNode = {
1161
+ __logicType: FakeType.Component,
1162
+ realParent: root,
1163
+ data: store,
1164
+ tokenizer
1165
+ };
1166
+ terp.program(root, componentNode);
1167
+ return [componentNode, store];
1107
1168
  };
1108
1169
  }
1109
1170