@weborigami/language 0.6.2 → 0.6.4
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/package.json +2 -2
- package/src/compiler/optimize.js +16 -11
- package/src/compiler/origami.pegjs +54 -29
- package/src/compiler/parse.js +440 -255
- package/src/compiler/parserHelpers.js +116 -29
- package/src/project/jsGlobals.js +2 -2
- package/src/runtime/expressionObject.js +42 -6
- package/src/runtime/ops.js +14 -18
- package/test/compiler/compile.test.js +14 -0
- package/test/compiler/parse.test.js +202 -65
- package/test/runtime/expressionObject.test.js +11 -0
- package/test/runtime/ops.test.js +14 -4
|
@@ -187,7 +187,112 @@ describe("Origami parser", () => {
|
|
|
187
187
|
});
|
|
188
188
|
|
|
189
189
|
describe("callExpression", () => {
|
|
190
|
-
test("
|
|
190
|
+
test("call chains", () => {
|
|
191
|
+
assertParse("callExpression", "(foo.js())('arg')", [
|
|
192
|
+
[[markers.traverse, [markers.reference, "foo.js"]], undefined],
|
|
193
|
+
[ops.literal, "arg"],
|
|
194
|
+
]);
|
|
195
|
+
assertParse("callExpression", "fn('a')('b')", [
|
|
196
|
+
[
|
|
197
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
198
|
+
[ops.literal, "a"],
|
|
199
|
+
],
|
|
200
|
+
[ops.literal, "b"],
|
|
201
|
+
]);
|
|
202
|
+
assertParse("callExpression", "(foo.js())(a, b)", [
|
|
203
|
+
[[markers.traverse, [markers.reference, "foo.js"]], undefined],
|
|
204
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
205
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
206
|
+
]);
|
|
207
|
+
assertParse("callExpression", "fn (x) (y) (z)", [
|
|
208
|
+
[
|
|
209
|
+
[
|
|
210
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
211
|
+
[markers.traverse, [markers.reference, "x"]],
|
|
212
|
+
],
|
|
213
|
+
[markers.traverse, [markers.reference, "y"]],
|
|
214
|
+
],
|
|
215
|
+
[markers.traverse, [markers.reference, "z"]],
|
|
216
|
+
]);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test("optional property access", () => {
|
|
220
|
+
assertParse("callExpression", "a?.b.c", [
|
|
221
|
+
ops.optional,
|
|
222
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
223
|
+
[
|
|
224
|
+
ops.lambda,
|
|
225
|
+
[[ops.literal, "__optional__"]],
|
|
226
|
+
[
|
|
227
|
+
ops.property,
|
|
228
|
+
[
|
|
229
|
+
ops.property,
|
|
230
|
+
[markers.traverse, [markers.reference, "__optional__"]],
|
|
231
|
+
[ops.literal, "b"],
|
|
232
|
+
],
|
|
233
|
+
[ops.literal, "c"],
|
|
234
|
+
],
|
|
235
|
+
],
|
|
236
|
+
]);
|
|
237
|
+
assertParse("callExpression", "a?.b?.c", [
|
|
238
|
+
ops.optional,
|
|
239
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
240
|
+
[
|
|
241
|
+
ops.lambda,
|
|
242
|
+
[[ops.literal, "__optional__"]],
|
|
243
|
+
[
|
|
244
|
+
ops.optional,
|
|
245
|
+
[
|
|
246
|
+
ops.property,
|
|
247
|
+
[markers.traverse, [markers.reference, "__optional__"]],
|
|
248
|
+
[ops.literal, "b"],
|
|
249
|
+
],
|
|
250
|
+
[
|
|
251
|
+
ops.lambda,
|
|
252
|
+
[[ops.literal, "__optional__"]],
|
|
253
|
+
[
|
|
254
|
+
ops.property,
|
|
255
|
+
[markers.traverse, [markers.reference, "__optional__"]],
|
|
256
|
+
[ops.literal, "c"],
|
|
257
|
+
],
|
|
258
|
+
],
|
|
259
|
+
],
|
|
260
|
+
],
|
|
261
|
+
]);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test("optional computed property access", () => {
|
|
265
|
+
assertParse("callExpression", "a?.[key]", [
|
|
266
|
+
ops.optional,
|
|
267
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
268
|
+
[
|
|
269
|
+
ops.lambda,
|
|
270
|
+
[[ops.literal, "__optional__"]],
|
|
271
|
+
[
|
|
272
|
+
ops.property,
|
|
273
|
+
[markers.traverse, [markers.reference, "__optional__"]],
|
|
274
|
+
[markers.traverse, [markers.reference, "key"]],
|
|
275
|
+
],
|
|
276
|
+
],
|
|
277
|
+
]);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("optional parentheses call", () => {
|
|
281
|
+
assertParse("callExpression", "fn?.(0)", [
|
|
282
|
+
ops.optional,
|
|
283
|
+
[markers.traverse, [markers.reference, "fn"]],
|
|
284
|
+
[
|
|
285
|
+
ops.lambda,
|
|
286
|
+
[[ops.literal, "__optional__"]],
|
|
287
|
+
[
|
|
288
|
+
[markers.traverse, [markers.reference, "__optional__"]],
|
|
289
|
+
[ops.literal, 0],
|
|
290
|
+
],
|
|
291
|
+
],
|
|
292
|
+
]);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("parentheses arguments", () => {
|
|
191
296
|
assertParse("callExpression", "fn()", [
|
|
192
297
|
[markers.traverse, [markers.reference, "fn"]],
|
|
193
298
|
undefined,
|
|
@@ -212,26 +317,20 @@ describe("Origami parser", () => {
|
|
|
212
317
|
]);
|
|
213
318
|
});
|
|
214
319
|
|
|
215
|
-
test("
|
|
216
|
-
assertParse("callExpression", "(
|
|
217
|
-
[[markers.traverse, [markers.reference, "
|
|
218
|
-
|
|
219
|
-
]);
|
|
220
|
-
assertParse("callExpression", "fn('a')('b')", [
|
|
320
|
+
test("parentheses arguments with spreads", () => {
|
|
321
|
+
assertParse("callExpression", "fn(a, ...b, ...c)", [
|
|
322
|
+
[ops.property, [markers.traverse, [markers.reference, "fn"]], "apply"],
|
|
323
|
+
null,
|
|
221
324
|
[
|
|
222
|
-
|
|
223
|
-
[ops.
|
|
325
|
+
ops.flat,
|
|
326
|
+
[ops.array, [markers.traverse, [markers.reference, "a"]]],
|
|
327
|
+
[markers.traverse, [markers.reference, "b"]],
|
|
328
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
224
329
|
],
|
|
225
|
-
[ops.literal, "b"],
|
|
226
|
-
]);
|
|
227
|
-
assertParse("callExpression", "(foo.js())(a, b)", [
|
|
228
|
-
[[markers.traverse, [markers.reference, "foo.js"]], undefined],
|
|
229
|
-
[markers.traverse, [markers.reference, "a"]],
|
|
230
|
-
[markers.traverse, [markers.reference, "b"]],
|
|
231
330
|
]);
|
|
232
331
|
});
|
|
233
332
|
|
|
234
|
-
test("
|
|
333
|
+
test("paths", () => {
|
|
235
334
|
assertParse("callExpression", "tree/", [
|
|
236
335
|
markers.traverse,
|
|
237
336
|
[markers.reference, "tree/"],
|
|
@@ -292,17 +391,6 @@ describe("Origami parser", () => {
|
|
|
292
391
|
]);
|
|
293
392
|
});
|
|
294
393
|
|
|
295
|
-
test("tagged templates", () => {
|
|
296
|
-
assertParse("callExpression", "indent`hello`", [
|
|
297
|
-
[markers.traverse, [markers.reference, "indent"]],
|
|
298
|
-
[ops.literal, ["hello"]],
|
|
299
|
-
]);
|
|
300
|
-
assertParse("callExpression", "fn.js`Hello, world.`", [
|
|
301
|
-
[markers.traverse, [markers.reference, "fn.js"]],
|
|
302
|
-
[ops.literal, ["Hello, world."]],
|
|
303
|
-
]);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
394
|
test("protocols", () => {
|
|
307
395
|
assertParse("callExpression", "files:src/assets", [
|
|
308
396
|
[markers.global, "files:"],
|
|
@@ -318,6 +406,17 @@ describe("Origami parser", () => {
|
|
|
318
406
|
[ops.literal, "env"],
|
|
319
407
|
]);
|
|
320
408
|
});
|
|
409
|
+
|
|
410
|
+
test("tagged templates", () => {
|
|
411
|
+
assertParse("callExpression", "indent`hello`", [
|
|
412
|
+
[markers.traverse, [markers.reference, "indent"]],
|
|
413
|
+
[ops.literal, ["hello"]],
|
|
414
|
+
]);
|
|
415
|
+
assertParse("callExpression", "fn.js`Hello, world.`", [
|
|
416
|
+
[markers.traverse, [markers.reference, "fn.js"]],
|
|
417
|
+
[ops.literal, ["Hello, world."]],
|
|
418
|
+
]);
|
|
419
|
+
});
|
|
321
420
|
});
|
|
322
421
|
|
|
323
422
|
test("commaExpression", () => {
|
|
@@ -768,6 +867,24 @@ Body`,
|
|
|
768
867
|
[ops.literal, "arg"],
|
|
769
868
|
],
|
|
770
869
|
]);
|
|
870
|
+
assertParse(
|
|
871
|
+
"implicitParenthesesCallExpression",
|
|
872
|
+
"concat a.json, ...b.json, c.json",
|
|
873
|
+
[
|
|
874
|
+
[
|
|
875
|
+
ops.property,
|
|
876
|
+
[markers.traverse, [markers.reference, "concat"]],
|
|
877
|
+
"apply",
|
|
878
|
+
],
|
|
879
|
+
null,
|
|
880
|
+
[
|
|
881
|
+
ops.flat,
|
|
882
|
+
[ops.array, [markers.traverse, [markers.reference, "a.json"]]],
|
|
883
|
+
[markers.traverse, [markers.reference, "b.json"]],
|
|
884
|
+
[ops.array, [markers.traverse, [markers.reference, "c.json"]]],
|
|
885
|
+
],
|
|
886
|
+
]
|
|
887
|
+
);
|
|
771
888
|
});
|
|
772
889
|
|
|
773
890
|
test("key", () => {
|
|
@@ -782,35 +899,6 @@ Body`,
|
|
|
782
899
|
assertParse("key", "package-lock.json", "package-lock.json");
|
|
783
900
|
});
|
|
784
901
|
|
|
785
|
-
test("list", () => {
|
|
786
|
-
assertParse("list", "1", [[ops.literal, 1]]);
|
|
787
|
-
assertParse("list", "1,2,3", [
|
|
788
|
-
[ops.literal, 1],
|
|
789
|
-
[ops.literal, 2],
|
|
790
|
-
[ops.literal, 3],
|
|
791
|
-
]);
|
|
792
|
-
assertParse("list", "1, 2, 3,", [
|
|
793
|
-
[ops.literal, 1],
|
|
794
|
-
[ops.literal, 2],
|
|
795
|
-
[ops.literal, 3],
|
|
796
|
-
]);
|
|
797
|
-
assertParse("list", "1 , 2 , 3", [
|
|
798
|
-
[ops.literal, 1],
|
|
799
|
-
[ops.literal, 2],
|
|
800
|
-
[ops.literal, 3],
|
|
801
|
-
]);
|
|
802
|
-
assertParse("list", "1\n2\n3", [
|
|
803
|
-
[ops.literal, 1],
|
|
804
|
-
[ops.literal, 2],
|
|
805
|
-
[ops.literal, 3],
|
|
806
|
-
]);
|
|
807
|
-
assertParse("list", "'a' , 'b' , 'c'", [
|
|
808
|
-
[ops.literal, "a"],
|
|
809
|
-
[ops.literal, "b"],
|
|
810
|
-
[ops.literal, "c"],
|
|
811
|
-
]);
|
|
812
|
-
});
|
|
813
|
-
|
|
814
902
|
test("logicalAndExpression", () => {
|
|
815
903
|
assertParse("logicalAndExpression", "true && false", [
|
|
816
904
|
ops.logicalAnd,
|
|
@@ -898,7 +986,7 @@ Body`,
|
|
|
898
986
|
});
|
|
899
987
|
|
|
900
988
|
describe("objectLiteral", () => {
|
|
901
|
-
|
|
989
|
+
test("basic objects", () => {
|
|
902
990
|
assertParse("objectLiteral", "{}", [ops.object]);
|
|
903
991
|
assertParse("objectLiteral", "{ a: 1, b }", [
|
|
904
992
|
ops.object,
|
|
@@ -991,7 +1079,7 @@ Body`,
|
|
|
991
1079
|
]);
|
|
992
1080
|
});
|
|
993
1081
|
|
|
994
|
-
|
|
1082
|
+
test("spreads", () => {
|
|
995
1083
|
assertParse("objectLiteral", "{ ...x }", [
|
|
996
1084
|
ops.unpack,
|
|
997
1085
|
[markers.traverse, [markers.reference, "x"]],
|
|
@@ -1019,6 +1107,16 @@ Body`,
|
|
|
1019
1107
|
["b", [ops.literal, 2]],
|
|
1020
1108
|
]);
|
|
1021
1109
|
});
|
|
1110
|
+
|
|
1111
|
+
test("computed property keys", () => {
|
|
1112
|
+
assertParse("objectLiteral", "{ [key]: value }", [
|
|
1113
|
+
ops.object,
|
|
1114
|
+
[
|
|
1115
|
+
[markers.traverse, [markers.reference, "key"]],
|
|
1116
|
+
[markers.traverse, [markers.reference, "value"]],
|
|
1117
|
+
],
|
|
1118
|
+
]);
|
|
1119
|
+
});
|
|
1022
1120
|
});
|
|
1023
1121
|
|
|
1024
1122
|
describe("objectEntry", () => {
|
|
@@ -1122,12 +1220,17 @@ Body`,
|
|
|
1122
1220
|
assertParse("objectPublicKey", `"foo bar"`, "foo bar", "shell", false);
|
|
1123
1221
|
});
|
|
1124
1222
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1223
|
+
test("optional", () => {
|
|
1224
|
+
assertParse("optional", "?.key", [
|
|
1225
|
+
ops.optional,
|
|
1226
|
+
[markers.property, [ops.literal, "key"]],
|
|
1227
|
+
]);
|
|
1228
|
+
assertParse("optional", "?.[index]", [
|
|
1229
|
+
ops.optional,
|
|
1230
|
+
[markers.property, [markers.traverse, [markers.reference, "index"]]],
|
|
1231
|
+
]);
|
|
1232
|
+
assertParse("optional", "?.(0)", [ops.optional, [[ops.literal, 0]]]);
|
|
1233
|
+
});
|
|
1131
1234
|
|
|
1132
1235
|
test("parenthesesArguments", () => {
|
|
1133
1236
|
assertParse("parenthesesArguments", "()", [undefined]);
|
|
@@ -1138,6 +1241,40 @@ Body`,
|
|
|
1138
1241
|
]);
|
|
1139
1242
|
});
|
|
1140
1243
|
|
|
1244
|
+
test("parenthesesArgumentList", () => {
|
|
1245
|
+
assertParse("parenthesesArgumentList", "1", [[ops.literal, 1]]);
|
|
1246
|
+
assertParse("parenthesesArgumentList", "1,2,3", [
|
|
1247
|
+
[ops.literal, 1],
|
|
1248
|
+
[ops.literal, 2],
|
|
1249
|
+
[ops.literal, 3],
|
|
1250
|
+
]);
|
|
1251
|
+
assertParse("parenthesesArgumentList", "1, 2, 3,", [
|
|
1252
|
+
[ops.literal, 1],
|
|
1253
|
+
[ops.literal, 2],
|
|
1254
|
+
[ops.literal, 3],
|
|
1255
|
+
]);
|
|
1256
|
+
assertParse("parenthesesArgumentList", "1 , 2 , 3", [
|
|
1257
|
+
[ops.literal, 1],
|
|
1258
|
+
[ops.literal, 2],
|
|
1259
|
+
[ops.literal, 3],
|
|
1260
|
+
]);
|
|
1261
|
+
assertParse("parenthesesArgumentList", "1\n2\n3", [
|
|
1262
|
+
[ops.literal, 1],
|
|
1263
|
+
[ops.literal, 2],
|
|
1264
|
+
[ops.literal, 3],
|
|
1265
|
+
]);
|
|
1266
|
+
assertParse("parenthesesArgumentList", "'a' , 'b' , 'c'", [
|
|
1267
|
+
[ops.literal, "a"],
|
|
1268
|
+
[ops.literal, "b"],
|
|
1269
|
+
[ops.literal, "c"],
|
|
1270
|
+
]);
|
|
1271
|
+
assertParse("parenthesesArgumentList", "a, ...b, c", [
|
|
1272
|
+
[markers.traverse, [markers.reference, "a"]],
|
|
1273
|
+
[markers.spread, [markers.traverse, [markers.reference, "b"]]],
|
|
1274
|
+
[markers.traverse, [markers.reference, "c"]],
|
|
1275
|
+
]);
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1141
1278
|
test("pathKeys", () => {
|
|
1142
1279
|
assertParse(
|
|
1143
1280
|
"pathKeys",
|
|
@@ -1360,7 +1497,7 @@ Body`,
|
|
|
1360
1497
|
|
|
1361
1498
|
test("spreadElement", () => {
|
|
1362
1499
|
assertParse("spreadElement", "...a", [
|
|
1363
|
-
|
|
1500
|
+
markers.spread,
|
|
1364
1501
|
[markers.traverse, [markers.reference, "a"]],
|
|
1365
1502
|
]);
|
|
1366
1503
|
});
|
|
@@ -52,6 +52,14 @@ describe("expressionObject", () => {
|
|
|
52
52
|
assert.equal(object[symbols.parent], context);
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
test("can compute a property key", async () => {
|
|
56
|
+
const entries = [[[ops.concat, "data", ".json"], 1]];
|
|
57
|
+
const context = new SyncMap();
|
|
58
|
+
const object = await expressionObject(entries, { object: context });
|
|
59
|
+
assert.equal(await object["data.json"], 1);
|
|
60
|
+
assert.deepEqual(object[symbols.keys](), ["data.json"]);
|
|
61
|
+
});
|
|
62
|
+
|
|
55
63
|
test("returned object values can be unpacked", async () => {
|
|
56
64
|
const entries = [["data.json", `{ "a": 1 }`]];
|
|
57
65
|
const context = new SyncMap();
|
|
@@ -79,6 +87,8 @@ describe("expressionObject", () => {
|
|
|
79
87
|
["message", "Hello"],
|
|
80
88
|
// Immediate maplike value, should have a slash
|
|
81
89
|
["object", [ops.object, ["b", [ops.literal, 2]]]],
|
|
90
|
+
// Computed key
|
|
91
|
+
[[ops.concat, [ops.array, "data", ".json"]], 1],
|
|
82
92
|
];
|
|
83
93
|
const object = await expressionObject(entries);
|
|
84
94
|
assert.deepEqual(object[symbols.keys](), [
|
|
@@ -86,6 +96,7 @@ describe("expressionObject", () => {
|
|
|
86
96
|
"hasSlash/",
|
|
87
97
|
"message",
|
|
88
98
|
"object/",
|
|
99
|
+
"data.json",
|
|
89
100
|
]);
|
|
90
101
|
});
|
|
91
102
|
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -304,10 +304,20 @@ describe("ops", () => {
|
|
|
304
304
|
assert.strictEqual(ops.multiplication("foo", 2), NaN);
|
|
305
305
|
});
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
test("ops.optional", async () => {
|
|
308
|
+
assert.equal(
|
|
309
|
+
ops.optional(null, (x) => x.a),
|
|
310
|
+
undefined
|
|
311
|
+
);
|
|
312
|
+
assert.equal(
|
|
313
|
+
ops.optional(undefined, (x) => x.a),
|
|
314
|
+
undefined
|
|
315
|
+
);
|
|
316
|
+
assert.equal(
|
|
317
|
+
ops.optional({ a: 1 }, (x) => x.a),
|
|
318
|
+
1
|
|
319
|
+
);
|
|
320
|
+
});
|
|
311
321
|
|
|
312
322
|
test("ops.notEqual", () => {
|
|
313
323
|
assert(!ops.notEqual(1, 1));
|