bobe 0.0.18 → 0.0.20

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
@@ -12,6 +12,7 @@ var TokenType = /* @__PURE__ */ ((TokenType2) => {
12
12
  TokenType2[TokenType2["Pipe"] = 32] = "Pipe";
13
13
  TokenType2[TokenType2["Eof"] = 64] = "Eof";
14
14
  TokenType2[TokenType2["InsertionExp"] = 128] = "InsertionExp";
15
+ TokenType2[TokenType2["Semicolon"] = 256] = "Semicolon";
15
16
  return TokenType2;
16
17
  })(TokenType || {});
17
18
  var FakeType = /* @__PURE__ */ ((FakeType2) => {
@@ -35,7 +36,6 @@ var NodeSort = /* @__PURE__ */ ((NodeSort2) => {
35
36
  NodeSort2[NodeSort2["TokenizerSwitcher"] = 16] = "TokenizerSwitcher";
36
37
  return NodeSort2;
37
38
  })(NodeSort || {});
38
- const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
39
39
 
40
40
  class MultiTypeStack {
41
41
  constructor() {
@@ -130,17 +130,33 @@ class MultiTypeStack {
130
130
  // }
131
131
  }
132
132
 
133
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
134
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
135
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
136
+ var __objRest = (source, exclude) => {
137
+ var target = {};
138
+ for (var prop in source)
139
+ if (__hasOwnProp$1.call(source, prop) && exclude.indexOf(prop) < 0)
140
+ target[prop] = source[prop];
141
+ if (source != null && __getOwnPropSymbols$1)
142
+ for (var prop of __getOwnPropSymbols$1(source)) {
143
+ if (exclude.indexOf(prop) < 0 && __propIsEnum$1.call(source, prop))
144
+ target[prop] = source[prop];
145
+ }
146
+ return target;
147
+ };
133
148
  new bobeShared.BaseEvent();
134
149
  class Interpreter {
135
150
  constructor(tokenizer) {
136
151
  this.tokenizer = tokenizer;
137
152
  this.rootComponent = null;
153
+ this.forItemId = 0;
138
154
  this.oneRealPropParsed = this.onePropParsed.bind(this);
139
155
  }
140
156
  isLogicNode(node) {
141
157
  return node && node.__logicType & LogicalBit;
142
158
  }
143
- program(root, componentNode, before) {
159
+ program(root, componentNode, before, ctxProvider) {
144
160
  var _a, _b;
145
161
  this.rootComponent = componentNode;
146
162
  this.tokenizer.nextToken();
@@ -150,6 +166,12 @@ class Interpreter {
150
166
  { node: componentNode, prev: null },
151
167
  NodeSort.Component | NodeSort.CtxProvider | NodeSort.TokenizerSwitcher
152
168
  );
169
+ if (ctxProvider) {
170
+ stack.push(
171
+ { node: ctxProvider, prev: null },
172
+ (ctxProvider.__logicType & LogicalBit ? NodeSort.Logic : 0) | NodeSort.CtxProvider
173
+ );
174
+ }
153
175
  const ctx = this.ctx = {
154
176
  realParent: root,
155
177
  prevSibling: before,
@@ -213,6 +235,21 @@ class Interpreter {
213
235
  const switcher = (_b = stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _b.node;
214
236
  this.tokenizer = switcher.tokenizer;
215
237
  }
238
+ if (parent.__logicType === FakeType.ForItem) {
239
+ const { forNode } = parent;
240
+ const { i, arr, snapshot } = forNode;
241
+ if (i + 1 < arr.length) {
242
+ this.tokenizer.resume(snapshot);
243
+ this.tokenizer.nextToken();
244
+ this.tokenizer.nextToken();
245
+ ctx.prevSibling = parent;
246
+ ctx.current = forNode.children[++forNode.i];
247
+ continue;
248
+ }
249
+ ctx.prevSibling = forNode.prevSibling;
250
+ ctx.current = forNode;
251
+ continue;
252
+ }
216
253
  }
217
254
  ctx.prevSibling = prev;
218
255
  ctx.current = parent;
@@ -223,15 +260,10 @@ class Interpreter {
223
260
  }
224
261
  return componentNode;
225
262
  }
226
- switcherIsRootComponent() {
227
- var _a;
228
- const currentSwitcher = (_a = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
229
- return currentSwitcher === this.rootComponent;
230
- }
231
- insertAfterAnchor(ctx) {
232
- const { realParent, prevSibling, stack, before } = ctx;
233
- const afterAnchor = this.createAnchor();
234
- ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
263
+ insertAfterAnchor(name = "anchor") {
264
+ const { realParent, prevSibling, stack, before } = this.ctx;
265
+ const afterAnchor = this.createAnchor(name);
266
+ this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
235
267
  this.handleInsert(realParent, afterAnchor, prevSibling);
236
268
  return afterAnchor;
237
269
  }
@@ -253,7 +285,7 @@ class Interpreter {
253
285
  const childCmp = child;
254
286
  childCmp.realParent = parent;
255
287
  if (prev == null ? void 0 : prev.__logicType) {
256
- childCmp.realBefore = prev.realAfter;
288
+ childCmp.realBefore = prev.forNode ? prev.forNode.realAfter : prev.realAfter;
257
289
  } else {
258
290
  childCmp.realBefore = prev;
259
291
  }
@@ -282,7 +314,10 @@ class Interpreter {
282
314
  let _node;
283
315
  if (value === "if" || value === "else" || value === "fail") {
284
316
  return this.condDeclaration(ctx);
317
+ } else if (value === "for") {
318
+ return this.forDeclaration();
285
319
  } else if (hookType) {
320
+ const data = this.getData();
286
321
  if (hookType === "static") {
287
322
  if (typeof value === "function") {
288
323
  _node = this.componentOrFragmentDeclaration(value, ctx);
@@ -290,7 +325,15 @@ class Interpreter {
290
325
  throw new SyntaxError(`declaration \u4E0D\u652F\u6301 ${value} \u7C7B\u578B\u7684\u9759\u6001\u63D2\u503C`);
291
326
  }
292
327
  } else {
293
- _node = this.componentOrFragmentDeclaration(value, ctx);
328
+ const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
329
+ const val = data[aoye.Keys.Raw][value];
330
+ if (typeof val === "function") {
331
+ _node = this.componentOrFragmentDeclaration(val, ctx);
332
+ } else {
333
+ const str = valueIsMapKey ? value : this.getFn(data, value);
334
+ _node = this.createNode("text");
335
+ this.onePropParsed(data, _node, "text", str, valueIsMapKey, false);
336
+ }
294
337
  }
295
338
  } else {
296
339
  _node = this.createNode(value);
@@ -304,6 +347,183 @@ class Interpreter {
304
347
  }
305
348
  return _node;
306
349
  }
350
+ forDeclaration() {
351
+ var _a;
352
+ const arrExp = this.tokenizer.nextToken().value;
353
+ this.tokenizer.nextToken();
354
+ const itemToken = this.tokenizer.nextToken();
355
+ const isDestruct = itemToken.type === TokenType.InsertionExp;
356
+ let itemExp = itemToken.value;
357
+ if (isDestruct) {
358
+ itemExp = "{" + itemExp + "}";
359
+ const vars = itemExp.match(bobeShared.jsVarRegexp).join(",");
360
+ itemExp = new Function("item", `let ${vars}; (${itemExp}=item); return {${vars}};`);
361
+ }
362
+ let indexName, keyExp;
363
+ while (this.tokenizer.code[this.tokenizer.i] !== "\n") {
364
+ const next = this.tokenizer.nextToken();
365
+ if (next.type !== TokenType.Semicolon) {
366
+ if (!indexName) {
367
+ indexName = next.value;
368
+ } else {
369
+ keyExp = next.value;
370
+ }
371
+ }
372
+ }
373
+ const owner = (_a = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
374
+ const prevSibling = this.ctx.prevSibling;
375
+ const forNode = {
376
+ __logicType: FakeType.For,
377
+ snapshot: this.tokenizer.snapshot(["dentStack", "isFirstToken"]),
378
+ realParent: this.ctx.realParent,
379
+ prevSibling,
380
+ realBefore: (prevSibling == null ? void 0 : prevSibling.realAfter) || prevSibling,
381
+ realAfter: null,
382
+ arr: null,
383
+ itemExp,
384
+ indexName,
385
+ getKey: null,
386
+ children: [],
387
+ effect: null,
388
+ owner,
389
+ i: 0
390
+ };
391
+ if (keyExp) {
392
+ forNode.getKey = new Function("data", `let v;with(data){v=${keyExp}};return v;`);
393
+ }
394
+ window["for1"] = forNode;
395
+ const data = this.getData();
396
+ const cells = data[aoye.Keys.Meta].cells;
397
+ const hasArrExpKey = Reflect.has(data[aoye.Keys.Raw], arrExp);
398
+ const arrSignal = hasArrExpKey ? (
399
+ // 有 key 直接拿
400
+ (data[arrExp], cells.get(arrExp))
401
+ ) : (
402
+ // 无key
403
+ aoye.$(this.getFn(data, arrExp))
404
+ );
405
+ forNode.realAfter = this.insertAfterAnchor("for-after");
406
+ const _b = forNode.snapshot, { dentStack, isFirstToken } = _b, snapshotForUpdate = __objRest(_b, ["dentStack", "isFirstToken"]);
407
+ let isFirstRender = true;
408
+ forNode.effect = aoye.effect(() => {
409
+ var _a2;
410
+ let arr = forNode.arr = arrSignal.v;
411
+ arr[aoye.Keys.Iterator];
412
+ arr = aoye.toRaw(arr);
413
+ const children = forNode.children;
414
+ if (isFirstRender) {
415
+ const len = arr.length;
416
+ for (let i = len; i--; ) {
417
+ const nextItem = children[i + 1];
418
+ const item = this.createForItem(forNode, i, data);
419
+ const anchor = this.insertAfterAnchor("for-item-after");
420
+ item.realAfter = anchor;
421
+ if (nextItem) {
422
+ nextItem.realBefore = anchor;
423
+ }
424
+ item.realParent = forNode.realParent;
425
+ children[i] = item;
426
+ }
427
+ const firstInsert = children[0];
428
+ if (firstInsert) {
429
+ firstInsert.realBefore = forNode.realBefore;
430
+ this.tokenizer.nextToken();
431
+ this.tokenizer.nextToken();
432
+ } else {
433
+ this.tokenizer.skip();
434
+ }
435
+ } else {
436
+ const oldLen = children.length;
437
+ const newLen = arr.length;
438
+ const minLen = Math.min(oldLen, newLen);
439
+ const newChildren = [];
440
+ if (!forNode.getKey) {
441
+ if (newLen < oldLen) {
442
+ for (let i = oldLen - 1; i >= newLen; i--) {
443
+ const child = children[i];
444
+ this.removeLogicNode(child);
445
+ this.remove(child.realAfter);
446
+ child.effect();
447
+ }
448
+ }
449
+ if (oldLen < newLen) {
450
+ const lastAfter = ((_a2 = children.at(-1)) == null ? void 0 : _a2.realAfter) || forNode.realBefore;
451
+ for (let i = newLen - 1; i >= oldLen; i--) {
452
+ const item = this.createForItem(forNode, i, data);
453
+ newChildren[i] = item;
454
+ const nextItem = newChildren[i + 1];
455
+ const anchor = this.createAnchor("for-item-after");
456
+ this.insertAfter(forNode.realParent, anchor, lastAfter);
457
+ item.realAfter = anchor;
458
+ if (nextItem) {
459
+ nextItem.realBefore = anchor;
460
+ }
461
+ item.realParent = forNode.realParent;
462
+ this.tokenizer = owner.tokenizer;
463
+ this.tokenizer.resume(snapshotForUpdate);
464
+ this.tokenizer.useDedentAsEof = false;
465
+ aoye.runWithPulling(() => {
466
+ this.program(forNode.realParent, forNode.owner, lastAfter, item);
467
+ }, item.effect.ins);
468
+ }
469
+ const firstInsert = newChildren[oldLen];
470
+ if (firstInsert) {
471
+ firstInsert.realBefore = lastAfter;
472
+ }
473
+ }
474
+ for (let i = minLen; i--; ) {
475
+ const child = children[i];
476
+ newChildren[i] = child;
477
+ if (typeof itemExp === "string") {
478
+ child.data[itemExp] = arr[i];
479
+ } else {
480
+ Object.assign(child.data, itemExp(arr[i]));
481
+ }
482
+ }
483
+ forNode.children = newChildren;
484
+ }
485
+ }
486
+ isFirstRender = false;
487
+ });
488
+ return forNode.children[0] || forNode;
489
+ }
490
+ createForItem(forNode, i, parentData) {
491
+ let forItemNode;
492
+ const effect2 = aoye.scope(() => {
493
+ }, null);
494
+ const { arr, itemExp, indexName, getKey } = forNode;
495
+ let data;
496
+ if (typeof itemExp === "string") {
497
+ data = aoye.$(
498
+ indexName ? {
499
+ [itemExp]: arr[i],
500
+ [indexName]: i
501
+ } : {
502
+ [itemExp]: arr[i]
503
+ }
504
+ );
505
+ } else {
506
+ const rawData = itemExp(arr[i]);
507
+ if (indexName) {
508
+ rawData[indexName] = i;
509
+ }
510
+ data = aoye.$(rawData);
511
+ }
512
+ Object.setPrototypeOf(data, parentData);
513
+ forItemNode = {
514
+ id: this.forItemId++,
515
+ __logicType: FakeType.ForItem,
516
+ realParent: null,
517
+ realBefore: null,
518
+ realAfter: null,
519
+ forNode,
520
+ key: getKey == null ? void 0 : getKey(data),
521
+ effect: null,
522
+ data
523
+ };
524
+ forItemNode.effect = effect2;
525
+ return forItemNode;
526
+ }
307
527
  getData() {
308
528
  const { node } = this.ctx.stack.peekByType(NodeSort.CtxProvider);
309
529
  return node.data || node.owner.data;
@@ -335,104 +555,89 @@ class Interpreter {
335
555
  }
336
556
  componentOrFragmentDeclaration(ComponentOrRender, ctx) {
337
557
  let Component, render, child;
338
- const data = this.getData();
339
- if (typeof ComponentOrRender === "string") {
340
- ComponentOrRender = data[ComponentOrRender];
341
- }
342
558
  const isCC = ComponentOrRender.prototype instanceof aoye.Store;
343
559
  if (isCC) {
344
560
  Component = ComponentOrRender;
345
561
  child = Component.new();
346
562
  } else {
347
563
  render = ComponentOrRender;
564
+ const boundStore = render.boundStore;
348
565
  child = aoye.deepSignal({}, aoye.getPulling(), true);
349
- Object.setPrototypeOf(child, data);
566
+ Object.setPrototypeOf(child, boundStore);
350
567
  }
351
568
  const node = {
352
569
  __logicType: isCC ? FakeType.Component : FakeType.Fragment,
353
570
  realParent: ctx.realParent,
571
+ realBefore: null,
572
+ realAfter: null,
354
573
  data: child,
355
574
  tokenizer: render ? render(true) : child["ui"](true)
356
575
  };
357
- this.onePropParsed = (data2, _, key, value, valueIsMapKey, isFn, hookI) => {
576
+ this.onePropParsed = (data, _, key, value, valueIsMapKey, isFn, hookI) => {
358
577
  if (isFn) {
359
578
  child[aoye.Keys.Raw][key] = value;
360
579
  } else if (valueIsMapKey) {
361
- aoye.shareSignal(data2, value, child, key);
362
- } else if (typeof value === "function") {
580
+ aoye.shareSignal(data, value, child, key);
581
+ } else {
363
582
  const meta = child[aoye.Keys.Meta];
364
583
  const cells = meta.cells;
365
- const computed = aoye.$(value);
366
- cells.set(key, computed);
367
- } else {
368
- child[aoye.Keys.Raw][key] = value;
584
+ if (typeof value === "function") {
585
+ const computed = aoye.$(value);
586
+ cells.set(key, computed);
587
+ child[aoye.Keys.Raw][key] = void 0;
588
+ } else {
589
+ cells.set(key, { v: value });
590
+ child[aoye.Keys.Raw][key] = value;
591
+ }
369
592
  }
370
593
  };
371
- node.realAfter = this.insertAfterAnchor(ctx);
594
+ node.realAfter = this.insertAfterAnchor("component-after");
372
595
  return node;
373
596
  }
597
+ getFn(data, expression) {
598
+ return new Function("data", `let v;with(data){v=${expression}};return v;`).bind(void 0, data);
599
+ }
374
600
  // TODO: 优化代码逻辑,拆分 if elseif else
375
601
  condDeclaration(ctx) {
376
602
  var _a;
377
603
  const { prevSibling } = ctx;
378
- const snapbackUp = this.tokenizer.snapshot();
379
604
  const keyWord = this.tokenizer.token;
380
- this.tokenizer.nextToken();
381
- const noSelfCond = this.tokenizer.token.type === TokenType.NewLine;
382
- const [hookType, value] = this.tokenizer._hook({});
605
+ const expToken = this.tokenizer.condExp();
606
+ const value = expToken.value;
383
607
  const isElse = keyWord.value === "else";
384
608
  const isIf = keyWord.value === "if";
385
609
  const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondBit;
386
- const needCalcWithPrevIf = isElse && preIsCond;
387
610
  const data = this.getData();
611
+ const noCond = value === true;
612
+ const valueIsMapKey = !noCond && Reflect.has(data[aoye.Keys.Raw], value);
388
613
  const owner = (_a = ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
389
614
  const ifNode = {
390
615
  __logicType: isElse ? FakeType.Else : isIf ? FakeType.If : FakeType.Fail,
391
- snapshot: noSelfCond ? snapbackUp : this.tokenizer.snapshot(),
392
- condition: null,
616
+ // 此时 token exp, 下次解析 从 \n 开始
617
+ snapshot: this.tokenizer.snapshot(),
393
618
  realParent: null,
619
+ realBefore: null,
620
+ realAfter: null,
621
+ condition: null,
394
622
  preCond: preIsCond ? prevSibling : null,
395
623
  isFirstRender: true,
396
624
  effect: null,
397
625
  owner
398
626
  };
399
627
  let signal;
400
- if (noSelfCond) {
401
- if (isElse) {
402
- signal = aoye.$(() => {
403
- let point = ifNode.preCond;
404
- while (point) {
405
- if (point.condition.v) {
406
- return false;
407
- }
408
- if (point.__logicType === FakeType.If) {
409
- break;
410
- }
411
- point = point.preCond;
412
- }
413
- return true;
414
- });
415
- } else {
416
- signal = aoye.$(() => {
417
- let point = ifNode.preCond;
418
- while (point) {
419
- if (point.condition.v) {
420
- return false;
421
- }
422
- point = point.preCond;
423
- }
424
- return true;
425
- });
426
- }
427
- } else {
428
- const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
429
- if (valueIsMapKey && !needCalcWithPrevIf) {
430
- aoye.runWithPulling(() => data[value], null);
431
- const { cells } = data[aoye.Keys.Meta];
432
- signal = cells.get(value);
433
- } else {
434
- const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
435
- if (needCalcWithPrevIf) {
628
+ switch (keyWord.value) {
629
+ case "if":
630
+ if (valueIsMapKey) {
631
+ aoye.runWithPulling(() => data[value], null);
632
+ const { cells } = data[aoye.Keys.Meta];
633
+ signal = cells.get(value);
634
+ } else {
635
+ const fn = this.getFn(data, value);
636
+ signal = aoye.$(fn);
637
+ }
638
+ break;
639
+ case "else":
640
+ if (noCond) {
436
641
  signal = aoye.$(() => {
437
642
  let point = ifNode.preCond;
438
643
  while (point) {
@@ -444,43 +649,57 @@ class Interpreter {
444
649
  }
445
650
  point = point.preCond;
446
651
  }
447
- return fn();
652
+ return true;
448
653
  });
449
654
  } else {
450
- signal = aoye.$(fn);
655
+ const fn = valueIsMapKey ? null : this.getFn(data, value);
656
+ signal = aoye.$(() => {
657
+ let point = ifNode.preCond;
658
+ while (point) {
659
+ if (point.condition.v) {
660
+ return false;
661
+ }
662
+ if (point.__logicType === FakeType.If) {
663
+ break;
664
+ }
665
+ point = point.preCond;
666
+ }
667
+ return valueIsMapKey ? data[value] : fn();
668
+ });
451
669
  }
452
- }
670
+ break;
671
+ case "fail":
672
+ signal = aoye.$(() => {
673
+ let point = ifNode.preCond;
674
+ while (point) {
675
+ if (point.condition.v) {
676
+ return false;
677
+ }
678
+ point = point.preCond;
679
+ }
680
+ return true;
681
+ });
682
+ break;
453
683
  }
454
684
  ifNode.condition = signal;
455
- ifNode.realAfter = this.insertAfterAnchor(ctx);
685
+ ifNode.realAfter = this.insertAfterAnchor(`${keyWord.value}-after`);
456
686
  ifNode.effect = aoye.effect(
457
687
  ({ val }) => {
458
688
  if (val) {
459
689
  if (ifNode.isFirstRender) {
460
- if (!noSelfCond) {
461
- this.tokenizer.nextToken();
462
- }
690
+ this.tokenizer.nextToken();
463
691
  this.tokenizer.nextToken();
464
692
  } else {
465
693
  this.tokenizer = ifNode.owner.tokenizer;
466
694
  this.tokenizer.resume(ifNode.snapshot);
467
- this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore);
695
+ this.tokenizer.useDedentAsEof = false;
696
+ this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore, ifNode);
468
697
  }
469
698
  } else {
470
699
  if (ifNode.isFirstRender) {
471
- if (noSelfCond) {
472
- this.tokenizer.i = this.tokenizer.i - 1;
473
- this.tokenizer.needIndent = false;
474
- }
475
700
  this.tokenizer.skip();
476
701
  } else {
477
- const { realBefore, realAfter, realParent } = ifNode;
478
- let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
479
- while (point !== realAfter) {
480
- const next = this.nextSib(point);
481
- this.remove(point, realParent, realBefore);
482
- point = next;
483
- }
702
+ this.removeLogicNode(ifNode);
484
703
  }
485
704
  }
486
705
  ifNode.isFirstRender = false;
@@ -489,6 +708,15 @@ class Interpreter {
489
708
  );
490
709
  return ifNode;
491
710
  }
711
+ removeLogicNode(node) {
712
+ const { realBefore, realAfter, realParent } = node;
713
+ let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
714
+ while (point !== realAfter) {
715
+ const next = this.nextSib(point);
716
+ this.remove(point, realParent, realBefore);
717
+ point = next;
718
+ }
719
+ }
492
720
  /**
493
721
  * <extensionLines> ::= PIPE <attributeList> NEWLINE <extensionLines>
494
722
  * | ε
@@ -539,7 +767,7 @@ class Interpreter {
539
767
  const isFn = typeof rawVal === "function";
540
768
  if (hookType === "dynamic") {
541
769
  const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
542
- const fn = isFn ? rawVal : valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
770
+ const fn = isFn ? rawVal : valueIsMapKey ? value : this.getFn(data, value);
543
771
  this.onePropParsed(data, _node, key, fn, valueIsMapKey, isFn, hookI);
544
772
  } else if (hookType === "static") {
545
773
  this.onePropParsed(data, _node, key, value, false, isFn, hookI);
@@ -569,14 +797,9 @@ class Interpreter {
569
797
  firstChild(node) {
570
798
  return node.firstChild;
571
799
  }
572
- _createAnchor() {
573
- const anchor = this.createAnchor();
574
- anchor[IsAnchor] = true;
575
- return anchor;
576
- }
577
- createAnchor() {
800
+ createAnchor(name) {
578
801
  return {
579
- name: "anchor",
802
+ name,
580
803
  nextSibling: null
581
804
  };
582
805
  }
@@ -632,9 +855,9 @@ var __spreadValues = (a, b) => {
632
855
  };
633
856
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
634
857
  const _Tokenizer = class _Tokenizer {
635
- constructor(hook, isSubToken) {
858
+ constructor(hook, useDedentAsEof) {
636
859
  this.hook = hook;
637
- this.isSubToken = isSubToken;
860
+ this.useDedentAsEof = useDedentAsEof;
638
861
  /** 缩进大小 默认 2 */
639
862
  this.TabSize = 2;
640
863
  /** 缩进字符 */
@@ -679,7 +902,7 @@ const _Tokenizer = class _Tokenizer {
679
902
  }
680
903
  return [hookType, value];
681
904
  };
682
- if (isSubToken) {
905
+ if (useDedentAsEof) {
683
906
  this.setToken(TokenType.Indent, "");
684
907
  this.isFirstToken = true;
685
908
  }
@@ -697,11 +920,20 @@ const _Tokenizer = class _Tokenizer {
697
920
  this.dentStack = [0];
698
921
  Object.assign(this, _snapshot);
699
922
  }
700
- snapshot() {
701
- return {
923
+ snapshot(keys) {
924
+ const snap = {
702
925
  i: this.i,
703
926
  waitingTokens: this.waitingTokens.clone()
704
927
  };
928
+ if (keys) {
929
+ for (const k of keys) {
930
+ snap[k] = this[k];
931
+ if (k === "dentStack") {
932
+ snap[k] = this[k].slice();
933
+ }
934
+ }
935
+ }
936
+ return snap;
705
937
  }
706
938
  skip() {
707
939
  const logicDentLen = this.dentStack[this.dentStack.length - 1];
@@ -815,17 +1047,21 @@ ${_Tokenizer.EofId}`;
815
1047
  this.str(char);
816
1048
  break;
817
1049
  case "{":
818
- this.brace();
1050
+ const braceToken = this.brace();
1051
+ this.setToken(TokenType.InsertionExp, braceToken);
819
1052
  break;
820
1053
  case "$":
821
1054
  const handled = this.dynamic(char);
822
1055
  if (handled) break;
1056
+ case ";":
1057
+ this.setToken(TokenType.Semicolon, ";");
1058
+ break;
823
1059
  default:
824
1060
  if (bobeShared.isNum(char)) {
825
1061
  this.number(char);
826
1062
  break;
827
1063
  }
828
- if (typeof char === "string" && bobeShared.matchIdStart(char)) {
1064
+ if (typeof char === "string" && bobeShared.matchIdStart2(char, 0)) {
829
1065
  this.identifier(char);
830
1066
  }
831
1067
  break;
@@ -844,6 +1080,58 @@ ${_Tokenizer.EofId}`;
844
1080
  this.handledTokens.push(this.token);
845
1081
  }
846
1082
  }
1083
+ condExp() {
1084
+ let value = "";
1085
+ this.token = null;
1086
+ while (1) {
1087
+ const char = this.code[this.i];
1088
+ if (char === "\n") {
1089
+ break;
1090
+ }
1091
+ value += char;
1092
+ this.i++;
1093
+ }
1094
+ value = value.trim();
1095
+ this.setToken(TokenType.Identifier, value || true);
1096
+ return this.token;
1097
+ }
1098
+ /**
1099
+ * 解析到 for 时使用这个方法获取 for 后方的子表达式
1100
+ * 表达式通过 “;” 分割
1101
+ * // 最多可有三个表达式
1102
+ * for arr ; item index; item.key
1103
+ * @returns {boolean} 是否含有 key
1104
+ */
1105
+ forLoopSubExp() {
1106
+ this.token = null;
1107
+ let value = "";
1108
+ let count = 0;
1109
+ while (1) {
1110
+ const char = this.code[this.i];
1111
+ const isSemicolon = char === ";";
1112
+ if (isSemicolon || char === "\n") {
1113
+ value = value.trim();
1114
+ if (!this.token) {
1115
+ this.setToken(TokenType.Identifier, value);
1116
+ } else {
1117
+ this.waitingTokens.push({
1118
+ type: TokenType.Identifier,
1119
+ typeName: TokenType[TokenType.Identifier],
1120
+ value
1121
+ });
1122
+ }
1123
+ value = "";
1124
+ count++;
1125
+ if (count > 3) {
1126
+ throw SyntaxError(`for \u5FAA\u73AF\u6700\u591A\u53EF\u5305\u542B\u4E09\u4E2A\u8868\u8FBE\u5F0F, \u5206\u522B\u4E3A arr ; item index [; key]`);
1127
+ }
1128
+ if (!isSemicolon) return count === 3;
1129
+ } else {
1130
+ value += char;
1131
+ }
1132
+ this.i++;
1133
+ }
1134
+ }
847
1135
  assignment() {
848
1136
  this.setToken(TokenType.Assign, "=");
849
1137
  }
@@ -909,8 +1197,7 @@ ${_Tokenizer.EofId}`;
909
1197
  }
910
1198
  }
911
1199
  if (count === 0 && inString == null && inComment == null) {
912
- this.setToken(TokenType.InsertionExp, value.slice(1));
913
- return;
1200
+ return value.slice(1);
914
1201
  }
915
1202
  value += this.code[this.i];
916
1203
  this.i++;
@@ -1015,13 +1302,13 @@ ${_Tokenizer.EofId}`;
1015
1302
  const yes = this.dentStack.length === 1;
1016
1303
  if (yes) {
1017
1304
  if (!this.token) {
1018
- if (this.isSubToken) {
1305
+ if (this.useDedentAsEof) {
1019
1306
  this.setToken(TokenType.Dedent, "");
1020
1307
  } else {
1021
1308
  this.setToken(TokenType.Identifier, _Tokenizer.EofId);
1022
1309
  }
1023
1310
  } else {
1024
- if (this.isSubToken) {
1311
+ if (this.useDedentAsEof) {
1025
1312
  this.waitingTokens.push({
1026
1313
  type: TokenType.Dedent,
1027
1314
  typeName: TokenType[TokenType.Dedent],
@@ -1043,13 +1330,13 @@ ${_Tokenizer.EofId}`;
1043
1330
  let nextC;
1044
1331
  while (1) {
1045
1332
  nextC = this.code[this.i + 1];
1046
- if (typeof nextC !== "string" || !bobeShared.matchIdStart(nextC)) {
1333
+ if (typeof nextC !== "string" || !bobeShared.matchIdStart2(nextC, 0)) {
1047
1334
  break;
1048
1335
  }
1049
1336
  value += nextC;
1050
1337
  this.i++;
1051
1338
  }
1052
- if (value === _Tokenizer.EofId && this.isSubToken) {
1339
+ if (value === _Tokenizer.EofId && this.useDedentAsEof) {
1053
1340
  this.setToken(TokenType.Dedent, "");
1054
1341
  return;
1055
1342
  }
@@ -1118,6 +1405,7 @@ function bobe(fragments, ...values) {
1118
1405
  tokenizer.init(Array.from(fragments));
1119
1406
  return tokenizer;
1120
1407
  };
1408
+ ui.boundStore = aoye.Store.Current;
1121
1409
  return ui;
1122
1410
  }
1123
1411
  function customRender(option) {