bobe 0.0.19 → 0.0.21
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 +394 -109
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.esm.js +396 -111
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +43 -18
- package/dist/index.umd.js +394 -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,10 +554,6 @@ 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;
|
|
@@ -351,89 +567,76 @@ class Interpreter {
|
|
|
351
567
|
const node = {
|
|
352
568
|
__logicType: isCC ? FakeType.Component : FakeType.Fragment,
|
|
353
569
|
realParent: ctx.realParent,
|
|
570
|
+
realBefore: null,
|
|
571
|
+
realAfter: null,
|
|
354
572
|
data: child,
|
|
355
573
|
tokenizer: render ? render(true) : child["ui"](true)
|
|
356
574
|
};
|
|
357
|
-
this.onePropParsed = (
|
|
575
|
+
this.onePropParsed = (data, _, key, value, valueIsMapKey, isFn, hookI) => {
|
|
358
576
|
if (isFn) {
|
|
359
577
|
child[Keys.Raw][key] = value;
|
|
360
578
|
} else if (valueIsMapKey) {
|
|
361
|
-
shareSignal(
|
|
362
|
-
} else
|
|
579
|
+
shareSignal(data, value, child, key);
|
|
580
|
+
} else {
|
|
363
581
|
const meta = child[Keys.Meta];
|
|
364
582
|
const cells = meta.cells;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
+
}
|
|
370
591
|
}
|
|
371
592
|
};
|
|
372
|
-
node.realAfter = this.insertAfterAnchor(
|
|
593
|
+
node.realAfter = this.insertAfterAnchor("component-after");
|
|
373
594
|
return node;
|
|
374
595
|
}
|
|
596
|
+
getFn(data, expression) {
|
|
597
|
+
return new Function("data", `let v;with(data){v=${expression}};return v;`).bind(void 0, data);
|
|
598
|
+
}
|
|
375
599
|
// TODO: 优化代码逻辑,拆分 if elseif else
|
|
376
600
|
condDeclaration(ctx) {
|
|
377
601
|
var _a;
|
|
378
602
|
const { prevSibling } = ctx;
|
|
379
|
-
const snapbackUp = this.tokenizer.snapshot();
|
|
380
603
|
const keyWord = this.tokenizer.token;
|
|
381
|
-
this.tokenizer.
|
|
382
|
-
const
|
|
383
|
-
const [hookType, value] = this.tokenizer._hook({});
|
|
604
|
+
const expToken = this.tokenizer.condExp();
|
|
605
|
+
const value = expToken.value;
|
|
384
606
|
const isElse = keyWord.value === "else";
|
|
385
607
|
const isIf = keyWord.value === "if";
|
|
386
608
|
const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondBit;
|
|
387
|
-
const needCalcWithPrevIf = isElse && preIsCond;
|
|
388
609
|
const data = this.getData();
|
|
610
|
+
const noCond = value === true;
|
|
611
|
+
const valueIsMapKey = !noCond && Reflect.has(data[Keys.Raw], value);
|
|
389
612
|
const owner = (_a = ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
|
|
390
613
|
const ifNode = {
|
|
391
614
|
__logicType: isElse ? FakeType.Else : isIf ? FakeType.If : FakeType.Fail,
|
|
392
|
-
|
|
393
|
-
|
|
615
|
+
// 此时 token 是 exp, 下次解析 从 \n 开始
|
|
616
|
+
snapshot: this.tokenizer.snapshot(),
|
|
394
617
|
realParent: null,
|
|
618
|
+
realBefore: null,
|
|
619
|
+
realAfter: null,
|
|
620
|
+
condition: null,
|
|
395
621
|
preCond: preIsCond ? prevSibling : null,
|
|
396
622
|
isFirstRender: true,
|
|
397
623
|
effect: null,
|
|
398
624
|
owner
|
|
399
625
|
};
|
|
400
626
|
let signal;
|
|
401
|
-
|
|
402
|
-
if
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
return true;
|
|
415
|
-
});
|
|
416
|
-
} else {
|
|
417
|
-
signal = $(() => {
|
|
418
|
-
let point = ifNode.preCond;
|
|
419
|
-
while (point) {
|
|
420
|
-
if (point.condition.v) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
point = point.preCond;
|
|
424
|
-
}
|
|
425
|
-
return true;
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
} else {
|
|
429
|
-
const valueIsMapKey = Reflect.has(data[Keys.Raw], value);
|
|
430
|
-
if (valueIsMapKey && !needCalcWithPrevIf) {
|
|
431
|
-
runWithPulling(() => data[value], null);
|
|
432
|
-
const { cells } = data[Keys.Meta];
|
|
433
|
-
signal = cells.get(value);
|
|
434
|
-
} else {
|
|
435
|
-
const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
|
|
436
|
-
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) {
|
|
437
640
|
signal = $(() => {
|
|
438
641
|
let point = ifNode.preCond;
|
|
439
642
|
while (point) {
|
|
@@ -445,43 +648,57 @@ class Interpreter {
|
|
|
445
648
|
}
|
|
446
649
|
point = point.preCond;
|
|
447
650
|
}
|
|
448
|
-
return
|
|
651
|
+
return true;
|
|
449
652
|
});
|
|
450
653
|
} else {
|
|
451
|
-
|
|
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
|
+
});
|
|
452
668
|
}
|
|
453
|
-
|
|
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;
|
|
454
682
|
}
|
|
455
683
|
ifNode.condition = signal;
|
|
456
|
-
ifNode.realAfter = this.insertAfterAnchor(
|
|
684
|
+
ifNode.realAfter = this.insertAfterAnchor(`${keyWord.value}-after`);
|
|
457
685
|
ifNode.effect = effect(
|
|
458
686
|
({ val }) => {
|
|
459
687
|
if (val) {
|
|
460
688
|
if (ifNode.isFirstRender) {
|
|
461
|
-
|
|
462
|
-
this.tokenizer.nextToken();
|
|
463
|
-
}
|
|
689
|
+
this.tokenizer.nextToken();
|
|
464
690
|
this.tokenizer.nextToken();
|
|
465
691
|
} else {
|
|
466
692
|
this.tokenizer = ifNode.owner.tokenizer;
|
|
467
693
|
this.tokenizer.resume(ifNode.snapshot);
|
|
468
|
-
this.
|
|
694
|
+
this.tokenizer.useDedentAsEof = false;
|
|
695
|
+
this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore, ifNode);
|
|
469
696
|
}
|
|
470
697
|
} else {
|
|
471
698
|
if (ifNode.isFirstRender) {
|
|
472
|
-
if (noSelfCond) {
|
|
473
|
-
this.tokenizer.i = this.tokenizer.i - 1;
|
|
474
|
-
this.tokenizer.needIndent = false;
|
|
475
|
-
}
|
|
476
699
|
this.tokenizer.skip();
|
|
477
700
|
} else {
|
|
478
|
-
|
|
479
|
-
let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
|
|
480
|
-
while (point !== realAfter) {
|
|
481
|
-
const next = this.nextSib(point);
|
|
482
|
-
this.remove(point, realParent, realBefore);
|
|
483
|
-
point = next;
|
|
484
|
-
}
|
|
701
|
+
this.removeLogicNode(ifNode);
|
|
485
702
|
}
|
|
486
703
|
}
|
|
487
704
|
ifNode.isFirstRender = false;
|
|
@@ -490,6 +707,15 @@ class Interpreter {
|
|
|
490
707
|
);
|
|
491
708
|
return ifNode;
|
|
492
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
|
+
}
|
|
493
719
|
/**
|
|
494
720
|
* <extensionLines> ::= PIPE <attributeList> NEWLINE <extensionLines>
|
|
495
721
|
* | ε
|
|
@@ -540,7 +766,7 @@ class Interpreter {
|
|
|
540
766
|
const isFn = typeof rawVal === "function";
|
|
541
767
|
if (hookType === "dynamic") {
|
|
542
768
|
const valueIsMapKey = Reflect.has(data[Keys.Raw], value);
|
|
543
|
-
const fn = isFn ? rawVal : valueIsMapKey ? value :
|
|
769
|
+
const fn = isFn ? rawVal : valueIsMapKey ? value : this.getFn(data, value);
|
|
544
770
|
this.onePropParsed(data, _node, key, fn, valueIsMapKey, isFn, hookI);
|
|
545
771
|
} else if (hookType === "static") {
|
|
546
772
|
this.onePropParsed(data, _node, key, value, false, isFn, hookI);
|
|
@@ -570,14 +796,9 @@ class Interpreter {
|
|
|
570
796
|
firstChild(node) {
|
|
571
797
|
return node.firstChild;
|
|
572
798
|
}
|
|
573
|
-
|
|
574
|
-
const anchor = this.createAnchor();
|
|
575
|
-
anchor[IsAnchor] = true;
|
|
576
|
-
return anchor;
|
|
577
|
-
}
|
|
578
|
-
createAnchor() {
|
|
799
|
+
createAnchor(name) {
|
|
579
800
|
return {
|
|
580
|
-
name
|
|
801
|
+
name,
|
|
581
802
|
nextSibling: null
|
|
582
803
|
};
|
|
583
804
|
}
|
|
@@ -633,9 +854,9 @@ var __spreadValues = (a, b) => {
|
|
|
633
854
|
};
|
|
634
855
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
635
856
|
const _Tokenizer = class _Tokenizer {
|
|
636
|
-
constructor(hook,
|
|
857
|
+
constructor(hook, useDedentAsEof) {
|
|
637
858
|
this.hook = hook;
|
|
638
|
-
this.
|
|
859
|
+
this.useDedentAsEof = useDedentAsEof;
|
|
639
860
|
/** 缩进大小 默认 2 */
|
|
640
861
|
this.TabSize = 2;
|
|
641
862
|
/** 缩进字符 */
|
|
@@ -680,7 +901,7 @@ const _Tokenizer = class _Tokenizer {
|
|
|
680
901
|
}
|
|
681
902
|
return [hookType, value];
|
|
682
903
|
};
|
|
683
|
-
if (
|
|
904
|
+
if (useDedentAsEof) {
|
|
684
905
|
this.setToken(TokenType.Indent, "");
|
|
685
906
|
this.isFirstToken = true;
|
|
686
907
|
}
|
|
@@ -698,11 +919,20 @@ const _Tokenizer = class _Tokenizer {
|
|
|
698
919
|
this.dentStack = [0];
|
|
699
920
|
Object.assign(this, _snapshot);
|
|
700
921
|
}
|
|
701
|
-
snapshot() {
|
|
702
|
-
|
|
922
|
+
snapshot(keys) {
|
|
923
|
+
const snap = {
|
|
703
924
|
i: this.i,
|
|
704
925
|
waitingTokens: this.waitingTokens.clone()
|
|
705
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;
|
|
706
936
|
}
|
|
707
937
|
skip() {
|
|
708
938
|
const logicDentLen = this.dentStack[this.dentStack.length - 1];
|
|
@@ -816,17 +1046,21 @@ ${_Tokenizer.EofId}`;
|
|
|
816
1046
|
this.str(char);
|
|
817
1047
|
break;
|
|
818
1048
|
case "{":
|
|
819
|
-
this.brace();
|
|
1049
|
+
const braceToken = this.brace();
|
|
1050
|
+
this.setToken(TokenType.InsertionExp, braceToken);
|
|
820
1051
|
break;
|
|
821
1052
|
case "$":
|
|
822
1053
|
const handled = this.dynamic(char);
|
|
823
1054
|
if (handled) break;
|
|
1055
|
+
case ";":
|
|
1056
|
+
this.setToken(TokenType.Semicolon, ";");
|
|
1057
|
+
break;
|
|
824
1058
|
default:
|
|
825
1059
|
if (isNum(char)) {
|
|
826
1060
|
this.number(char);
|
|
827
1061
|
break;
|
|
828
1062
|
}
|
|
829
|
-
if (typeof char === "string" &&
|
|
1063
|
+
if (typeof char === "string" && matchIdStart2(char, 0)) {
|
|
830
1064
|
this.identifier(char);
|
|
831
1065
|
}
|
|
832
1066
|
break;
|
|
@@ -845,6 +1079,58 @@ ${_Tokenizer.EofId}`;
|
|
|
845
1079
|
this.handledTokens.push(this.token);
|
|
846
1080
|
}
|
|
847
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
|
+
}
|
|
848
1134
|
assignment() {
|
|
849
1135
|
this.setToken(TokenType.Assign, "=");
|
|
850
1136
|
}
|
|
@@ -910,8 +1196,7 @@ ${_Tokenizer.EofId}`;
|
|
|
910
1196
|
}
|
|
911
1197
|
}
|
|
912
1198
|
if (count === 0 && inString == null && inComment == null) {
|
|
913
|
-
|
|
914
|
-
return;
|
|
1199
|
+
return value.slice(1);
|
|
915
1200
|
}
|
|
916
1201
|
value += this.code[this.i];
|
|
917
1202
|
this.i++;
|
|
@@ -1016,13 +1301,13 @@ ${_Tokenizer.EofId}`;
|
|
|
1016
1301
|
const yes = this.dentStack.length === 1;
|
|
1017
1302
|
if (yes) {
|
|
1018
1303
|
if (!this.token) {
|
|
1019
|
-
if (this.
|
|
1304
|
+
if (this.useDedentAsEof) {
|
|
1020
1305
|
this.setToken(TokenType.Dedent, "");
|
|
1021
1306
|
} else {
|
|
1022
1307
|
this.setToken(TokenType.Identifier, _Tokenizer.EofId);
|
|
1023
1308
|
}
|
|
1024
1309
|
} else {
|
|
1025
|
-
if (this.
|
|
1310
|
+
if (this.useDedentAsEof) {
|
|
1026
1311
|
this.waitingTokens.push({
|
|
1027
1312
|
type: TokenType.Dedent,
|
|
1028
1313
|
typeName: TokenType[TokenType.Dedent],
|
|
@@ -1044,13 +1329,13 @@ ${_Tokenizer.EofId}`;
|
|
|
1044
1329
|
let nextC;
|
|
1045
1330
|
while (1) {
|
|
1046
1331
|
nextC = this.code[this.i + 1];
|
|
1047
|
-
if (typeof nextC !== "string" || !
|
|
1332
|
+
if (typeof nextC !== "string" || !matchIdStart2(nextC, 0)) {
|
|
1048
1333
|
break;
|
|
1049
1334
|
}
|
|
1050
1335
|
value += nextC;
|
|
1051
1336
|
this.i++;
|
|
1052
1337
|
}
|
|
1053
|
-
if (value === _Tokenizer.EofId && this.
|
|
1338
|
+
if (value === _Tokenizer.EofId && this.useDedentAsEof) {
|
|
1054
1339
|
this.setToken(TokenType.Dedent, "");
|
|
1055
1340
|
return;
|
|
1056
1341
|
}
|