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