bobe 0.0.73 → 0.0.75

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
@@ -19,6 +19,7 @@ let TokenType = function (TokenType) {
19
19
  TokenType[TokenType["Null"] = 8192] = "Null";
20
20
  TokenType[TokenType["Undefined"] = 16384] = "Undefined";
21
21
  TokenType[TokenType["Comment"] = 32768] = "Comment";
22
+ TokenType[TokenType["TypeArguments"] = 65536] = "TypeArguments";
22
23
  return TokenType;
23
24
  }({});
24
25
  const ChildrenSugarType = TokenType.String | TokenType.InsertionExp;
@@ -74,6 +75,7 @@ let ParseErrorCode = function (ParseErrorCode) {
74
75
  ParseErrorCode[ParseErrorCode["MISSING_COMMENT_SECOND_SLASH"] = 9015] = "MISSING_COMMENT_SECOND_SLASH";
75
76
  ParseErrorCode[ParseErrorCode["MISSING_PROP_ASSIGNMENT"] = 9016] = "MISSING_PROP_ASSIGNMENT";
76
77
  ParseErrorCode[ParseErrorCode["PIPE_IN_WRONG_CONTEXT"] = 9017] = "PIPE_IN_WRONG_CONTEXT";
78
+ ParseErrorCode[ParseErrorCode["UNCLOSED_TYPE_ARGUMENTS"] = 9018] = "UNCLOSED_TYPE_ARGUMENTS";
77
79
  return ParseErrorCode;
78
80
  }({});
79
81
  class ParseSyntaxError extends SyntaxError {
@@ -247,12 +249,13 @@ class Tokenizer {
247
249
  if (!this.token) return false;
248
250
  return this.token.type & TokenType.Identifier && this.token.value === Tokenizer.EofId;
249
251
  }
250
- setToken(type, value, dt = 1) {
252
+ setToken(type, value, dt = 1, extra) {
251
253
  this.token = {
252
254
  type,
253
255
  typeName: TokenType[type],
254
256
  value,
255
- loc: null
257
+ loc: null,
258
+ ...extra
256
259
  };
257
260
  this.isFirstToken = false;
258
261
  }
@@ -306,6 +309,9 @@ class Tokenizer {
306
309
  const braceToken = this.brace();
307
310
  this.setToken(TokenType.InsertionExp, braceToken);
308
311
  break;
312
+ case '<':
313
+ this.typeArguments();
314
+ break;
309
315
  case '$':
310
316
  const handled = this.staticIns();
311
317
  if (handled) break;
@@ -394,6 +400,104 @@ class Tokenizer {
394
400
  this.locEnd();
395
401
  return this.token;
396
402
  }
403
+ typeArguments() {
404
+ const startOffset = this.i;
405
+ const startLine = this.line;
406
+ const startColumn = this.column;
407
+ let angleDepth = 0;
408
+ let braceDepth = 0;
409
+ let bracketDepth = 0;
410
+ let parenDepth = 0;
411
+ let current = '';
412
+ const args = [];
413
+ let argStart = this.i + 1;
414
+ const makeLoc = (start, end) => ({
415
+ start: {
416
+ offset: start,
417
+ line: startLine,
418
+ column: startColumn + (start - startOffset)
419
+ },
420
+ end: {
421
+ offset: end,
422
+ line: startLine,
423
+ column: startColumn + (end - startOffset)
424
+ },
425
+ source: this.code.slice(start, end)
426
+ });
427
+ const pushArg = end => {
428
+ const raw = current.trim();
429
+ if (!raw) return;
430
+ const leading = current.length - current.trimStart().length;
431
+ const trailingEnd = current.trimEnd().length;
432
+ args.push({
433
+ raw,
434
+ loc: makeLoc(argStart + leading, argStart + trailingEnd)
435
+ });
436
+ };
437
+ while (true) {
438
+ const char = this.code[this.i];
439
+ if (char === undefined || char === '\n') {
440
+ throw new ParseSyntaxError(ParseErrorCode.UNCLOSED_TYPE_ARGUMENTS, '未闭合的组件泛型参数', makeLoc(startOffset, this.i));
441
+ }
442
+ if (char === '\'' || char === '"' || char === '`') {
443
+ const quote = char;
444
+ current += char;
445
+ this.next();
446
+ while (true) {
447
+ const inner = this.code[this.i];
448
+ if (inner === undefined || inner === '\n') {
449
+ throw new ParseSyntaxError(ParseErrorCode.UNCLOSED_TYPE_ARGUMENTS, '未闭合的组件泛型参数', makeLoc(startOffset, this.i));
450
+ }
451
+ current += inner;
452
+ if (inner === '\\') {
453
+ this.next();
454
+ current += this.code[this.i] ?? '';
455
+ } else if (inner === quote) {
456
+ break;
457
+ }
458
+ this.next();
459
+ }
460
+ } else if (char === '<') {
461
+ angleDepth++;
462
+ if (angleDepth > 1) current += char;
463
+ } else if (char === '>' && this.code[this.i - 1] !== '=') {
464
+ angleDepth--;
465
+ if (angleDepth === 0) {
466
+ pushArg(this.i);
467
+ this.setToken(TokenType.TypeArguments, this.code.slice(startOffset + 1, this.i), 1, {
468
+ typeArguments: args
469
+ });
470
+ return;
471
+ }
472
+ current += char;
473
+ } else if (char === '{') {
474
+ braceDepth++;
475
+ current += char;
476
+ } else if (char === '}') {
477
+ braceDepth = Math.max(0, braceDepth - 1);
478
+ current += char;
479
+ } else if (char === '[') {
480
+ bracketDepth++;
481
+ current += char;
482
+ } else if (char === ']') {
483
+ bracketDepth = Math.max(0, bracketDepth - 1);
484
+ current += char;
485
+ } else if (char === '(') {
486
+ parenDepth++;
487
+ current += char;
488
+ } else if (char === ')') {
489
+ parenDepth = Math.max(0, parenDepth - 1);
490
+ current += char;
491
+ } else if (char === ',' && angleDepth === 1 && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
492
+ pushArg(this.i);
493
+ current = '';
494
+ argStart = this.i + 1;
495
+ } else {
496
+ current += char;
497
+ }
498
+ this.next();
499
+ }
500
+ }
397
501
  peekChar() {
398
502
  let i = this.i;
399
503
  while (this.code[i] === ' ' || this.code[i] === '\t') {
@@ -1105,8 +1209,19 @@ class Compiler {
1105
1209
  parseComponentNode(node) {
1106
1210
  const name = this.parseName();
1107
1211
  this.tokenizer.nextToken();
1212
+ const typeArgumentsToken = this.tokenizer.token.type & TokenType.TypeArguments ? this.tokenizer.token : undefined;
1213
+ if (typeArgumentsToken) {
1214
+ this.tokenizer.nextToken();
1215
+ }
1108
1216
  node.type = NodeType.Component;
1109
1217
  node.componentName = name;
1218
+ node.typeArguments = typeArgumentsToken?.typeArguments?.map(arg => ({
1219
+ type: NodeType.StaticValue,
1220
+ raw: arg.raw,
1221
+ loc: arg.loc
1222
+ }));
1223
+ node.typeArgumentsLoc = typeArgumentsToken?.loc;
1224
+ this.hooks.parseComponentNode?.nameAdded?.call(this, node);
1110
1225
  const props = this.headerLineAndExtensions();
1111
1226
  node.props = props;
1112
1227
  this.hooks.parseComponentNode?.propsAdded?.call(this, node);
@@ -1694,6 +1809,7 @@ class Interpreter {
1694
1809
  _node = this.createNode(value);
1695
1810
  }
1696
1811
  this.tokenizer.nextToken();
1812
+ this.skipComponentTypeArguments(_node);
1697
1813
  this.headerLineAndExtensions(_node);
1698
1814
  this.onePropParsed = this.oneRealPropParsed;
1699
1815
  if (_node.__logicType & TokenizerSwitcherBit) {
@@ -1747,6 +1863,7 @@ class Interpreter {
1747
1863
  }, NodeSort.CtxProvider);
1748
1864
  }
1749
1865
  this.tokenizer.nextToken();
1866
+ this.skipComponentTypeArguments(node);
1750
1867
  this.headerLineAndExtensions(node);
1751
1868
  if (isUpdate) {
1752
1869
  this.ctx.stack.pop();
@@ -1776,6 +1893,7 @@ class Interpreter {
1776
1893
  this.handleInsert(node.realParent, textNode, node.realBefore);
1777
1894
  } else {
1778
1895
  this.tokenizer.nextToken();
1896
+ this.skipComponentTypeArguments(node, true);
1779
1897
  this.headerLineAndExtensions(node);
1780
1898
  const _this$ctx2 = this.ctx,
1781
1899
  realParent = _this$ctx2.realParent,
@@ -2381,6 +2499,11 @@ class Interpreter {
2381
2499
  getFn(data, expression) {
2382
2500
  return new Function('data', `with(data){return (${expression})}`).bind(undefined, safe(data));
2383
2501
  }
2502
+ getBoolFn(data, expression) {
2503
+ return new Function('data', `with(data){return Boolean(${expression})}`).bind(undefined, safeExclude(data, {
2504
+ 'Boolean': true
2505
+ }));
2506
+ }
2384
2507
  getAssignFn(data, expression) {
2385
2508
  const valueId = `value_bobe_${date32()}`;
2386
2509
  return new Function('data', valueId, `with(data){${expression}=${valueId}};`).bind(undefined, safeExclude(data, {
@@ -2418,11 +2541,9 @@ class Interpreter {
2418
2541
  switch (keyWord.value) {
2419
2542
  case 'if':
2420
2543
  if (valueIsMapKey) {
2421
- runWithPulling(() => data[value], null);
2422
- const cells = data[Keys.Meta].cells;
2423
- signal = cells.get(value);
2544
+ signal = new Computed(() => Boolean(data[value]));
2424
2545
  } else {
2425
- const fn = this.getFn(data, value);
2546
+ const fn = this.getBoolFn(data, value);
2426
2547
  signal = new Computed(fn);
2427
2548
  }
2428
2549
  break;
@@ -2442,7 +2563,7 @@ class Interpreter {
2442
2563
  return true;
2443
2564
  });
2444
2565
  } else {
2445
- const fn = valueIsMapKey ? null : this.getFn(data, value);
2566
+ const fn = valueIsMapKey ? null : this.getBoolFn(data, value);
2446
2567
  signal = new Computed(() => {
2447
2568
  let point = ifNode.preCond;
2448
2569
  while (point) {
@@ -2454,7 +2575,7 @@ class Interpreter {
2454
2575
  }
2455
2576
  point = point.preCond;
2456
2577
  }
2457
- return valueIsMapKey ? data[value] : fn();
2578
+ return valueIsMapKey ? Boolean(data[value]) : fn();
2458
2579
  });
2459
2580
  }
2460
2581
  break;
@@ -2511,6 +2632,11 @@ class Interpreter {
2511
2632
  point = next;
2512
2633
  }
2513
2634
  }
2635
+ skipComponentTypeArguments(node, force = false) {
2636
+ if ((force || node.__logicType & TokenizerSwitcherBit) && this.tokenizer.token.type & TokenType.TypeArguments) {
2637
+ this.tokenizer.nextToken();
2638
+ }
2639
+ }
2514
2640
  headerLineAndExtensions(_node) {
2515
2641
  const tokenizer = this.tokenizer;
2516
2642
  do {
@@ -2860,5 +2986,5 @@ const effect = (callback, depOrOpt, opt) => {
2860
2986
  return effect$1(callback, option);
2861
2987
  };
2862
2988
 
2863
- export { Compiler, FakeType, Interpreter, Mw, MwCtx, NodeType, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
2989
+ export { Compiler, FakeType, Interpreter, Mw, MwCtx, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
2864
2990
  //# sourceMappingURL=bobe.esm.js.map