@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.
@@ -187,7 +187,112 @@ describe("Origami parser", () => {
187
187
  });
188
188
 
189
189
  describe("callExpression", () => {
190
- test("with parentheses arguments", () => {
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("call chains", () => {
216
- assertParse("callExpression", "(foo.js())('arg')", [
217
- [[markers.traverse, [markers.reference, "foo.js"]], undefined],
218
- [ops.literal, "arg"],
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
- [markers.traverse, [markers.reference, "fn"]],
223
- [ops.literal, "a"],
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("with paths", () => {
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
- describe("basic objects", () => {
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
- describe("spreads", () => {
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
- // test.skip("optionalChaining", () => {
1126
- // assertParse("optionalChaining", "?.key", [
1127
- // ops.optionalTraverse,
1128
- // [ops.literal, "key"],
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
- ops.spread,
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
 
@@ -304,10 +304,20 @@ describe("ops", () => {
304
304
  assert.strictEqual(ops.multiplication("foo", 2), NaN);
305
305
  });
306
306
 
307
- // test("ops.optionalTraverse", async () => {
308
- // assert.equal(await ops.optionalTraverse(null, "a"), undefined);
309
- // assert.equal(await ops.optionalTraverse({ a: 1 }, "a"), 1);
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));