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.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
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
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
|
-
|
|
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,
|
|
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 = (
|
|
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(
|
|
362
|
-
} else
|
|
580
|
+
aoye.shareSignal(data, value, child, key);
|
|
581
|
+
} else {
|
|
363
582
|
const meta = child[aoye.Keys.Meta];
|
|
364
583
|
const cells = meta.cells;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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(
|
|
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.
|
|
381
|
-
const
|
|
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
|
-
|
|
392
|
-
|
|
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
|
-
|
|
401
|
-
if
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
|
652
|
+
return true;
|
|
448
653
|
});
|
|
449
654
|
} else {
|
|
450
|
-
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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 :
|
|
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
|
-
|
|
573
|
-
const anchor = this.createAnchor();
|
|
574
|
-
anchor[IsAnchor] = true;
|
|
575
|
-
return anchor;
|
|
576
|
-
}
|
|
577
|
-
createAnchor() {
|
|
800
|
+
createAnchor(name) {
|
|
578
801
|
return {
|
|
579
|
-
name
|
|
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,
|
|
858
|
+
constructor(hook, useDedentAsEof) {
|
|
636
859
|
this.hook = hook;
|
|
637
|
-
this.
|
|
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 (
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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) {
|