summitjs 0.1.0 → 0.2.0
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/summit.cjs +124 -9
- package/dist/summit.cjs.map +1 -1
- package/dist/summit.js +124 -9
- package/dist/summit.js.map +1 -1
- package/dist/summit.min.js +7 -6
- package/dist/summit.min.js.map +1 -1
- package/package.json +1 -1
package/dist/summit.js
CHANGED
|
@@ -339,6 +339,35 @@ function createScope(raw) {
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
// src/evaluator/lexer.ts
|
|
342
|
+
var REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
|
|
343
|
+
"return",
|
|
344
|
+
"typeof",
|
|
345
|
+
"void",
|
|
346
|
+
"in",
|
|
347
|
+
"instanceof",
|
|
348
|
+
"new",
|
|
349
|
+
"of",
|
|
350
|
+
"delete",
|
|
351
|
+
"do",
|
|
352
|
+
"else"
|
|
353
|
+
]);
|
|
354
|
+
function regexAllowed(prev) {
|
|
355
|
+
if (!prev) return true;
|
|
356
|
+
switch (prev.type) {
|
|
357
|
+
case "num":
|
|
358
|
+
case "str":
|
|
359
|
+
case "tmpl":
|
|
360
|
+
case "regex":
|
|
361
|
+
return false;
|
|
362
|
+
// a value precedes -> division
|
|
363
|
+
case "ident":
|
|
364
|
+
return REGEX_PRECEDING_KEYWORDS.has(prev.value);
|
|
365
|
+
case "punc":
|
|
366
|
+
return prev.value !== ")" && prev.value !== "]";
|
|
367
|
+
default:
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
342
371
|
var PUNCTUATORS = [
|
|
343
372
|
"...",
|
|
344
373
|
"===",
|
|
@@ -485,6 +514,35 @@ function tokenize(input) {
|
|
|
485
514
|
tokens2.push({ type: "ident", value: input.slice(start2, i), start: start2, end: i });
|
|
486
515
|
continue;
|
|
487
516
|
}
|
|
517
|
+
if (ch === "/" && regexAllowed(tokens2[tokens2.length - 1])) {
|
|
518
|
+
const start2 = i;
|
|
519
|
+
i++;
|
|
520
|
+
let body = "";
|
|
521
|
+
let inClass = false;
|
|
522
|
+
while (i < n) {
|
|
523
|
+
const c = input[i];
|
|
524
|
+
if (c === "\\") {
|
|
525
|
+
body += c + (input[i + 1] ?? "");
|
|
526
|
+
i += 2;
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
if (c === "\n") throw new LexError(`Unterminated regex in expression: ${input}`);
|
|
530
|
+
if (c === "[") inClass = true;
|
|
531
|
+
else if (c === "]") inClass = false;
|
|
532
|
+
else if (c === "/" && !inClass) break;
|
|
533
|
+
body += c;
|
|
534
|
+
i++;
|
|
535
|
+
}
|
|
536
|
+
if (input[i] !== "/") throw new LexError(`Unterminated regex in expression: ${input}`);
|
|
537
|
+
i++;
|
|
538
|
+
let flags = "";
|
|
539
|
+
while (i < n && /[a-z]/i.test(input[i])) {
|
|
540
|
+
flags += input[i];
|
|
541
|
+
i++;
|
|
542
|
+
}
|
|
543
|
+
tokens2.push({ type: "regex", value: body, flags, start: start2, end: i });
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
488
546
|
let matched = false;
|
|
489
547
|
for (const p of PUNCTUATORS) {
|
|
490
548
|
if (input.startsWith(p, i)) {
|
|
@@ -828,8 +886,34 @@ var Parser = class {
|
|
|
828
886
|
}
|
|
829
887
|
return node;
|
|
830
888
|
}
|
|
889
|
+
parseNewExpr() {
|
|
890
|
+
this.pos++;
|
|
891
|
+
let callee = this.parsePrimary();
|
|
892
|
+
for (; ; ) {
|
|
893
|
+
if (this.isPunc(".")) {
|
|
894
|
+
this.pos++;
|
|
895
|
+
const name = this.next();
|
|
896
|
+
callee = {
|
|
897
|
+
type: "MemberExpression",
|
|
898
|
+
object: callee,
|
|
899
|
+
property: { type: "Identifier", name: name.value },
|
|
900
|
+
computed: false,
|
|
901
|
+
optional: false
|
|
902
|
+
};
|
|
903
|
+
} else if (this.isPunc("[")) {
|
|
904
|
+
this.pos++;
|
|
905
|
+
const property = this.parseExpression();
|
|
906
|
+
this.eatPunc("]");
|
|
907
|
+
callee = { type: "MemberExpression", object: callee, property, computed: true, optional: false };
|
|
908
|
+
} else {
|
|
909
|
+
break;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
const args = this.isPunc("(") ? this.parseArguments() : [];
|
|
913
|
+
return { type: "NewExpression", callee, arguments: args };
|
|
914
|
+
}
|
|
831
915
|
parseCallMember() {
|
|
832
|
-
let node = this.parsePrimary();
|
|
916
|
+
let node = this.isKeyword("new") ? this.parseNewExpr() : this.parsePrimary();
|
|
833
917
|
for (; ; ) {
|
|
834
918
|
if (this.isPunc(".")) {
|
|
835
919
|
this.pos++;
|
|
@@ -904,6 +988,10 @@ var Parser = class {
|
|
|
904
988
|
this.pos++;
|
|
905
989
|
return this.parseTemplate(t.raw ?? "");
|
|
906
990
|
}
|
|
991
|
+
if (t.type === "regex") {
|
|
992
|
+
this.pos++;
|
|
993
|
+
return { type: "RegexLiteral", pattern: t.value, flags: t.flags ?? "" };
|
|
994
|
+
}
|
|
907
995
|
if (t.type === "ident") {
|
|
908
996
|
if (t.value === "true" || t.value === "false") {
|
|
909
997
|
this.pos++;
|
|
@@ -985,6 +1073,11 @@ var Parser = class {
|
|
|
985
1073
|
return { type: "ObjectExpression", properties };
|
|
986
1074
|
}
|
|
987
1075
|
parseObjectProperty() {
|
|
1076
|
+
if (this.isKeyword("async") && this.peek(1).type === "ident") {
|
|
1077
|
+
throw new ParseError(
|
|
1078
|
+
"async methods are not supported in Summit expressions. Use a regular method that returns a Promise and chain .then()."
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
988
1081
|
if ((this.isKeyword("get") || this.isKeyword("set")) && !this.isPunc(":", 1) && !this.isPunc(",", 1) && !this.isPunc("(", 1) && !this.isPunc("}", 1)) {
|
|
989
1082
|
const kind = this.next().value;
|
|
990
1083
|
const { key: key2, computed: computed3 } = this.parsePropertyKey();
|
|
@@ -1395,6 +1488,8 @@ var Interpreter = class {
|
|
|
1395
1488
|
return null;
|
|
1396
1489
|
case "UndefinedLiteral":
|
|
1397
1490
|
return void 0;
|
|
1491
|
+
case "RegexLiteral":
|
|
1492
|
+
return new RegExp(node.pattern, node.flags);
|
|
1398
1493
|
case "ThisExpression":
|
|
1399
1494
|
return thisVal;
|
|
1400
1495
|
case "Identifier":
|
|
@@ -1464,6 +1559,14 @@ var Interpreter = class {
|
|
|
1464
1559
|
}
|
|
1465
1560
|
case "CallExpression":
|
|
1466
1561
|
return this.evalCall(node, scope, thisVal);
|
|
1562
|
+
case "NewExpression": {
|
|
1563
|
+
const ctor = this.evalExpr(node.callee, scope, thisVal);
|
|
1564
|
+
const args = this.evalArguments(node.arguments, scope, thisVal);
|
|
1565
|
+
if (typeof ctor !== "function") {
|
|
1566
|
+
throw new TypeError("Expression value is not a constructor");
|
|
1567
|
+
}
|
|
1568
|
+
return Reflect.construct(ctor, args);
|
|
1569
|
+
}
|
|
1467
1570
|
case "ArrowFunction":
|
|
1468
1571
|
return this.makeFunction(
|
|
1469
1572
|
node,
|
|
@@ -2043,15 +2146,26 @@ function initData(el, dmeta, parentScopes) {
|
|
|
2043
2146
|
const parentEnv = makeEnv(el);
|
|
2044
2147
|
const expr = dmeta.expression.trim();
|
|
2045
2148
|
let raw;
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2149
|
+
try {
|
|
2150
|
+
const match = expr.match(DATA_PROVIDER_RE);
|
|
2151
|
+
if (match && getData(match[1])) {
|
|
2152
|
+
const provider = getData(match[1]);
|
|
2153
|
+
const args = match[2] ? parentEnv.evaluate("[" + (match[3] ?? "") + "]") : [];
|
|
2154
|
+
raw = provider(...args);
|
|
2155
|
+
} else if (expr === "") {
|
|
2156
|
+
raw = {};
|
|
2157
|
+
} else {
|
|
2158
|
+
raw = parentEnv.evaluate("(" + expr + ")");
|
|
2159
|
+
}
|
|
2160
|
+
} catch (err) {
|
|
2161
|
+
fail("E104", "s-data could not be evaluated; the component starts with empty state.", {
|
|
2162
|
+
el,
|
|
2163
|
+
expression: expr,
|
|
2164
|
+
doc: "s-data",
|
|
2165
|
+
hint: "Check the object for unsupported syntax, e.g. an async method.",
|
|
2166
|
+
cause: err
|
|
2167
|
+
});
|
|
2052
2168
|
raw = {};
|
|
2053
|
-
} else {
|
|
2054
|
-
raw = parentEnv.evaluate("(" + expr + ")");
|
|
2055
2169
|
}
|
|
2056
2170
|
if (raw === null || typeof raw !== "object") raw = {};
|
|
2057
2171
|
const scope = createScope(raw);
|
|
@@ -2808,6 +2922,7 @@ var sFor = (el, meta2, utils) => {
|
|
|
2808
2922
|
blocks.delete(key);
|
|
2809
2923
|
} else {
|
|
2810
2924
|
const node = blueprint.cloneNode(true);
|
|
2925
|
+
parent.insertBefore(node, anchor2);
|
|
2811
2926
|
utils.initTree(node, [...parentScopes, scope]);
|
|
2812
2927
|
next.set(key, { node, scope });
|
|
2813
2928
|
}
|