summitjs 0.1.0 → 0.3.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/README.md +38 -0
- package/dist/net.cjs +259 -0
- package/dist/net.cjs.map +1 -0
- package/dist/net.d.cts +134 -0
- package/dist/net.d.ts +134 -0
- package/dist/net.js +252 -0
- package/dist/net.js.map +1 -0
- package/dist/summit.cjs +147 -18
- package/dist/summit.cjs.map +1 -1
- package/dist/summit.js +147 -18
- 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 +11 -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();
|
|
@@ -1268,6 +1361,10 @@ var GLOBAL_ALLOW = /* @__PURE__ */ new Set([
|
|
|
1268
1361
|
"requestAnimationFrame",
|
|
1269
1362
|
"cancelAnimationFrame",
|
|
1270
1363
|
"fetch",
|
|
1364
|
+
"AbortController",
|
|
1365
|
+
"Headers",
|
|
1366
|
+
"Request",
|
|
1367
|
+
"Response",
|
|
1271
1368
|
"alert",
|
|
1272
1369
|
"confirm",
|
|
1273
1370
|
"prompt",
|
|
@@ -1395,6 +1492,8 @@ var Interpreter = class {
|
|
|
1395
1492
|
return null;
|
|
1396
1493
|
case "UndefinedLiteral":
|
|
1397
1494
|
return void 0;
|
|
1495
|
+
case "RegexLiteral":
|
|
1496
|
+
return new RegExp(node.pattern, node.flags);
|
|
1398
1497
|
case "ThisExpression":
|
|
1399
1498
|
return thisVal;
|
|
1400
1499
|
case "Identifier":
|
|
@@ -1464,6 +1563,14 @@ var Interpreter = class {
|
|
|
1464
1563
|
}
|
|
1465
1564
|
case "CallExpression":
|
|
1466
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
|
+
}
|
|
1467
1574
|
case "ArrowFunction":
|
|
1468
1575
|
return this.makeFunction(
|
|
1469
1576
|
node,
|
|
@@ -1705,6 +1812,10 @@ function evaluateAction(source, root, thisVal) {
|
|
|
1705
1812
|
const program = parse(source, "program");
|
|
1706
1813
|
return new Interpreter(root).run(program, thisVal);
|
|
1707
1814
|
}
|
|
1815
|
+
function compileExpression(source) {
|
|
1816
|
+
const program = parse(source, "expression");
|
|
1817
|
+
return (root, thisVal) => new Interpreter(root).run(program, thisVal);
|
|
1818
|
+
}
|
|
1708
1819
|
|
|
1709
1820
|
// src/errors.ts
|
|
1710
1821
|
var DOCS = "https://velofy.github.io/summit";
|
|
@@ -2043,15 +2154,26 @@ function initData(el, dmeta, parentScopes) {
|
|
|
2043
2154
|
const parentEnv = makeEnv(el);
|
|
2044
2155
|
const expr = dmeta.expression.trim();
|
|
2045
2156
|
let raw;
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2157
|
+
try {
|
|
2158
|
+
const match = expr.match(DATA_PROVIDER_RE);
|
|
2159
|
+
if (match && getData(match[1])) {
|
|
2160
|
+
const provider = getData(match[1]);
|
|
2161
|
+
const args = match[2] ? parentEnv.evaluate("[" + (match[3] ?? "") + "]") : [];
|
|
2162
|
+
raw = provider(...args);
|
|
2163
|
+
} else if (expr === "") {
|
|
2164
|
+
raw = {};
|
|
2165
|
+
} else {
|
|
2166
|
+
raw = parentEnv.evaluate("(" + expr + ")");
|
|
2167
|
+
}
|
|
2168
|
+
} catch (err) {
|
|
2169
|
+
fail("E104", "s-data could not be evaluated; the component starts with empty state.", {
|
|
2170
|
+
el,
|
|
2171
|
+
expression: expr,
|
|
2172
|
+
doc: "s-data",
|
|
2173
|
+
hint: "Check the object for unsupported syntax, e.g. an async method.",
|
|
2174
|
+
cause: err
|
|
2175
|
+
});
|
|
2052
2176
|
raw = {};
|
|
2053
|
-
} else {
|
|
2054
|
-
raw = parentEnv.evaluate("(" + expr + ")");
|
|
2055
2177
|
}
|
|
2056
2178
|
if (raw === null || typeof raw !== "object") raw = {};
|
|
2057
2179
|
const scope = createScope(raw);
|
|
@@ -2771,11 +2893,13 @@ var sFor = (el, meta2, utils) => {
|
|
|
2771
2893
|
el.remove();
|
|
2772
2894
|
const parentScopes = utils.scopes;
|
|
2773
2895
|
let blocks = /* @__PURE__ */ new Map();
|
|
2774
|
-
const
|
|
2775
|
-
|
|
2776
|
-
|
|
2896
|
+
const keyEval = keyExpr ? compileExpression(keyExpr) : null;
|
|
2897
|
+
const keyFor = (it) => {
|
|
2898
|
+
if (!keyEval) return it.objectKey ?? it.index;
|
|
2899
|
+
const data = { [itemName]: it.value };
|
|
2900
|
+
if (indexName) data[indexName] = it.objectKey ?? it.index;
|
|
2777
2901
|
try {
|
|
2778
|
-
return
|
|
2902
|
+
return keyEval(makeEnv(el, data).env);
|
|
2779
2903
|
} catch {
|
|
2780
2904
|
return it.index;
|
|
2781
2905
|
}
|
|
@@ -2797,8 +2921,7 @@ var sFor = (el, meta2, utils) => {
|
|
|
2797
2921
|
const next = /* @__PURE__ */ new Map();
|
|
2798
2922
|
const orderedKeys = [];
|
|
2799
2923
|
for (const it of items) {
|
|
2800
|
-
|
|
2801
|
-
const key = keyFor(it, scope);
|
|
2924
|
+
const key = keyFor(it);
|
|
2802
2925
|
orderedKeys.push(key);
|
|
2803
2926
|
const existing = blocks.get(key);
|
|
2804
2927
|
if (existing) {
|
|
@@ -2807,7 +2930,9 @@ var sFor = (el, meta2, utils) => {
|
|
|
2807
2930
|
next.set(key, existing);
|
|
2808
2931
|
blocks.delete(key);
|
|
2809
2932
|
} else {
|
|
2933
|
+
const scope = makeBlockScope(it);
|
|
2810
2934
|
const node = blueprint.cloneNode(true);
|
|
2935
|
+
parent.insertBefore(node, anchor2);
|
|
2811
2936
|
utils.initTree(node, [...parentScopes, scope]);
|
|
2812
2937
|
next.set(key, { node, scope });
|
|
2813
2938
|
}
|
|
@@ -2816,9 +2941,13 @@ var sFor = (el, meta2, utils) => {
|
|
|
2816
2941
|
utils.destroyTree(block.node);
|
|
2817
2942
|
block.node.remove();
|
|
2818
2943
|
}
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2944
|
+
let expected = anchor2;
|
|
2945
|
+
for (let i = orderedKeys.length - 1; i >= 0; i--) {
|
|
2946
|
+
const node = next.get(orderedKeys[i]).node;
|
|
2947
|
+
if (node.nextSibling !== expected) {
|
|
2948
|
+
parent.insertBefore(node, expected);
|
|
2949
|
+
}
|
|
2950
|
+
expected = node;
|
|
2822
2951
|
}
|
|
2823
2952
|
blocks = next;
|
|
2824
2953
|
});
|