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 +397 -109
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.esm.js +399 -111
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +48 -19
- package/dist/index.umd.js +397 -109
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/bobe.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getPulling, setPulling, effect, Store, deepSignal,
|
|
1
|
+
import { getPulling, setPulling, Keys, $, effect, toRaw, scope, Store, deepSignal, shareSignal, runWithPulling } from 'aoye';
|
|
2
2
|
export * from 'aoye';
|
|
3
|
-
import { BaseEvent, Queue, isNum,
|
|
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
|
-
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
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
|
-
|
|
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,
|
|
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 = (
|
|
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(
|
|
361
|
-
} else
|
|
579
|
+
shareSignal(data, value, child, key);
|
|
580
|
+
} else {
|
|
362
581
|
const meta = child[Keys.Meta];
|
|
363
582
|
const cells = meta.cells;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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(
|
|
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.
|
|
380
|
-
const
|
|
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
|
-
|
|
391
|
-
|
|
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
|
-
|
|
400
|
-
if
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
651
|
+
return true;
|
|
447
652
|
});
|
|
448
653
|
} else {
|
|
449
|
-
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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 :
|
|
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
|
-
|
|
572
|
-
const anchor = this.createAnchor();
|
|
573
|
-
anchor[IsAnchor] = true;
|
|
574
|
-
return anchor;
|
|
575
|
-
}
|
|
576
|
-
createAnchor() {
|
|
799
|
+
createAnchor(name) {
|
|
577
800
|
return {
|
|
578
|
-
name
|
|
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,
|
|
857
|
+
constructor(hook, useDedentAsEof) {
|
|
635
858
|
this.hook = hook;
|
|
636
|
-
this.
|
|
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 (
|
|
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
|
-
|
|
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" &&
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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" || !
|
|
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.
|
|
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) {
|