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.cjs
CHANGED
|
@@ -343,6 +343,35 @@ function createScope(raw) {
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
// src/evaluator/lexer.ts
|
|
346
|
+
var REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
|
|
347
|
+
"return",
|
|
348
|
+
"typeof",
|
|
349
|
+
"void",
|
|
350
|
+
"in",
|
|
351
|
+
"instanceof",
|
|
352
|
+
"new",
|
|
353
|
+
"of",
|
|
354
|
+
"delete",
|
|
355
|
+
"do",
|
|
356
|
+
"else"
|
|
357
|
+
]);
|
|
358
|
+
function regexAllowed(prev) {
|
|
359
|
+
if (!prev) return true;
|
|
360
|
+
switch (prev.type) {
|
|
361
|
+
case "num":
|
|
362
|
+
case "str":
|
|
363
|
+
case "tmpl":
|
|
364
|
+
case "regex":
|
|
365
|
+
return false;
|
|
366
|
+
// a value precedes -> division
|
|
367
|
+
case "ident":
|
|
368
|
+
return REGEX_PRECEDING_KEYWORDS.has(prev.value);
|
|
369
|
+
case "punc":
|
|
370
|
+
return prev.value !== ")" && prev.value !== "]";
|
|
371
|
+
default:
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
346
375
|
var PUNCTUATORS = [
|
|
347
376
|
"...",
|
|
348
377
|
"===",
|
|
@@ -489,6 +518,35 @@ function tokenize(input) {
|
|
|
489
518
|
tokens2.push({ type: "ident", value: input.slice(start2, i), start: start2, end: i });
|
|
490
519
|
continue;
|
|
491
520
|
}
|
|
521
|
+
if (ch === "/" && regexAllowed(tokens2[tokens2.length - 1])) {
|
|
522
|
+
const start2 = i;
|
|
523
|
+
i++;
|
|
524
|
+
let body = "";
|
|
525
|
+
let inClass = false;
|
|
526
|
+
while (i < n) {
|
|
527
|
+
const c = input[i];
|
|
528
|
+
if (c === "\\") {
|
|
529
|
+
body += c + (input[i + 1] ?? "");
|
|
530
|
+
i += 2;
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
if (c === "\n") throw new LexError(`Unterminated regex in expression: ${input}`);
|
|
534
|
+
if (c === "[") inClass = true;
|
|
535
|
+
else if (c === "]") inClass = false;
|
|
536
|
+
else if (c === "/" && !inClass) break;
|
|
537
|
+
body += c;
|
|
538
|
+
i++;
|
|
539
|
+
}
|
|
540
|
+
if (input[i] !== "/") throw new LexError(`Unterminated regex in expression: ${input}`);
|
|
541
|
+
i++;
|
|
542
|
+
let flags = "";
|
|
543
|
+
while (i < n && /[a-z]/i.test(input[i])) {
|
|
544
|
+
flags += input[i];
|
|
545
|
+
i++;
|
|
546
|
+
}
|
|
547
|
+
tokens2.push({ type: "regex", value: body, flags, start: start2, end: i });
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
492
550
|
let matched = false;
|
|
493
551
|
for (const p of PUNCTUATORS) {
|
|
494
552
|
if (input.startsWith(p, i)) {
|
|
@@ -832,8 +890,34 @@ var Parser = class {
|
|
|
832
890
|
}
|
|
833
891
|
return node;
|
|
834
892
|
}
|
|
893
|
+
parseNewExpr() {
|
|
894
|
+
this.pos++;
|
|
895
|
+
let callee = this.parsePrimary();
|
|
896
|
+
for (; ; ) {
|
|
897
|
+
if (this.isPunc(".")) {
|
|
898
|
+
this.pos++;
|
|
899
|
+
const name = this.next();
|
|
900
|
+
callee = {
|
|
901
|
+
type: "MemberExpression",
|
|
902
|
+
object: callee,
|
|
903
|
+
property: { type: "Identifier", name: name.value },
|
|
904
|
+
computed: false,
|
|
905
|
+
optional: false
|
|
906
|
+
};
|
|
907
|
+
} else if (this.isPunc("[")) {
|
|
908
|
+
this.pos++;
|
|
909
|
+
const property = this.parseExpression();
|
|
910
|
+
this.eatPunc("]");
|
|
911
|
+
callee = { type: "MemberExpression", object: callee, property, computed: true, optional: false };
|
|
912
|
+
} else {
|
|
913
|
+
break;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
const args = this.isPunc("(") ? this.parseArguments() : [];
|
|
917
|
+
return { type: "NewExpression", callee, arguments: args };
|
|
918
|
+
}
|
|
835
919
|
parseCallMember() {
|
|
836
|
-
let node = this.parsePrimary();
|
|
920
|
+
let node = this.isKeyword("new") ? this.parseNewExpr() : this.parsePrimary();
|
|
837
921
|
for (; ; ) {
|
|
838
922
|
if (this.isPunc(".")) {
|
|
839
923
|
this.pos++;
|
|
@@ -908,6 +992,10 @@ var Parser = class {
|
|
|
908
992
|
this.pos++;
|
|
909
993
|
return this.parseTemplate(t.raw ?? "");
|
|
910
994
|
}
|
|
995
|
+
if (t.type === "regex") {
|
|
996
|
+
this.pos++;
|
|
997
|
+
return { type: "RegexLiteral", pattern: t.value, flags: t.flags ?? "" };
|
|
998
|
+
}
|
|
911
999
|
if (t.type === "ident") {
|
|
912
1000
|
if (t.value === "true" || t.value === "false") {
|
|
913
1001
|
this.pos++;
|
|
@@ -989,6 +1077,11 @@ var Parser = class {
|
|
|
989
1077
|
return { type: "ObjectExpression", properties };
|
|
990
1078
|
}
|
|
991
1079
|
parseObjectProperty() {
|
|
1080
|
+
if (this.isKeyword("async") && this.peek(1).type === "ident") {
|
|
1081
|
+
throw new ParseError(
|
|
1082
|
+
"async methods are not supported in Summit expressions. Use a regular method that returns a Promise and chain .then()."
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
992
1085
|
if ((this.isKeyword("get") || this.isKeyword("set")) && !this.isPunc(":", 1) && !this.isPunc(",", 1) && !this.isPunc("(", 1) && !this.isPunc("}", 1)) {
|
|
993
1086
|
const kind = this.next().value;
|
|
994
1087
|
const { key: key2, computed: computed3 } = this.parsePropertyKey();
|
|
@@ -1399,6 +1492,8 @@ var Interpreter = class {
|
|
|
1399
1492
|
return null;
|
|
1400
1493
|
case "UndefinedLiteral":
|
|
1401
1494
|
return void 0;
|
|
1495
|
+
case "RegexLiteral":
|
|
1496
|
+
return new RegExp(node.pattern, node.flags);
|
|
1402
1497
|
case "ThisExpression":
|
|
1403
1498
|
return thisVal;
|
|
1404
1499
|
case "Identifier":
|
|
@@ -1468,6 +1563,14 @@ var Interpreter = class {
|
|
|
1468
1563
|
}
|
|
1469
1564
|
case "CallExpression":
|
|
1470
1565
|
return this.evalCall(node, scope, thisVal);
|
|
1566
|
+
case "NewExpression": {
|
|
1567
|
+
const ctor = this.evalExpr(node.callee, scope, thisVal);
|
|
1568
|
+
const args = this.evalArguments(node.arguments, scope, thisVal);
|
|
1569
|
+
if (typeof ctor !== "function") {
|
|
1570
|
+
throw new TypeError("Expression value is not a constructor");
|
|
1571
|
+
}
|
|
1572
|
+
return Reflect.construct(ctor, args);
|
|
1573
|
+
}
|
|
1471
1574
|
case "ArrowFunction":
|
|
1472
1575
|
return this.makeFunction(
|
|
1473
1576
|
node,
|
|
@@ -2047,15 +2150,26 @@ function initData(el, dmeta, parentScopes) {
|
|
|
2047
2150
|
const parentEnv = makeEnv(el);
|
|
2048
2151
|
const expr = dmeta.expression.trim();
|
|
2049
2152
|
let raw;
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2153
|
+
try {
|
|
2154
|
+
const match = expr.match(DATA_PROVIDER_RE);
|
|
2155
|
+
if (match && getData(match[1])) {
|
|
2156
|
+
const provider = getData(match[1]);
|
|
2157
|
+
const args = match[2] ? parentEnv.evaluate("[" + (match[3] ?? "") + "]") : [];
|
|
2158
|
+
raw = provider(...args);
|
|
2159
|
+
} else if (expr === "") {
|
|
2160
|
+
raw = {};
|
|
2161
|
+
} else {
|
|
2162
|
+
raw = parentEnv.evaluate("(" + expr + ")");
|
|
2163
|
+
}
|
|
2164
|
+
} catch (err) {
|
|
2165
|
+
fail("E104", "s-data could not be evaluated; the component starts with empty state.", {
|
|
2166
|
+
el,
|
|
2167
|
+
expression: expr,
|
|
2168
|
+
doc: "s-data",
|
|
2169
|
+
hint: "Check the object for unsupported syntax, e.g. an async method.",
|
|
2170
|
+
cause: err
|
|
2171
|
+
});
|
|
2056
2172
|
raw = {};
|
|
2057
|
-
} else {
|
|
2058
|
-
raw = parentEnv.evaluate("(" + expr + ")");
|
|
2059
2173
|
}
|
|
2060
2174
|
if (raw === null || typeof raw !== "object") raw = {};
|
|
2061
2175
|
const scope = createScope(raw);
|
|
@@ -2812,6 +2926,7 @@ var sFor = (el, meta2, utils) => {
|
|
|
2812
2926
|
blocks.delete(key);
|
|
2813
2927
|
} else {
|
|
2814
2928
|
const node = blueprint.cloneNode(true);
|
|
2929
|
+
parent.insertBefore(node, anchor2);
|
|
2815
2930
|
utils.initTree(node, [...parentScopes, scope]);
|
|
2816
2931
|
next.set(key, { node, scope });
|
|
2817
2932
|
}
|