@weborigami/language 0.6.1 → 0.6.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -11,7 +11,7 @@
11
11
  "typescript": "5.9.3"
12
12
  },
13
13
  "dependencies": {
14
- "@weborigami/async-tree": "0.6.1",
14
+ "@weborigami/async-tree": "0.6.2",
15
15
  "exif-parser": "0.1.12",
16
16
  "watcher": "2.3.1",
17
17
  "yaml": "2.8.1"
@@ -690,6 +690,8 @@ relationalOperator
690
690
  / "<"
691
691
  / ">="
692
692
  / ">"
693
+ / "instanceof"
694
+ / "in"
693
695
 
694
696
  separator
695
697
  = __ "," __
@@ -396,17 +396,19 @@ function peg$parse(input, options) {
396
396
  const peg$c55 = "?.";
397
397
  const peg$c56 = "<=";
398
398
  const peg$c57 = ">=";
399
- const peg$c58 = "#!";
400
- const peg$c59 = "<<";
401
- const peg$c60 = ">>>";
402
- const peg$c61 = ">>";
403
- const peg$c62 = "\u2192";
404
- const peg$c63 = "->";
405
- const peg$c64 = "${";
406
- const peg$c65 = "~";
407
- const peg$c66 = "await";
408
- const peg$c67 = "typeof";
409
- const peg$c68 = "void";
399
+ const peg$c58 = "instanceof";
400
+ const peg$c59 = "in";
401
+ const peg$c60 = "#!";
402
+ const peg$c61 = "<<";
403
+ const peg$c62 = ">>>";
404
+ const peg$c63 = ">>";
405
+ const peg$c64 = "\u2192";
406
+ const peg$c65 = "->";
407
+ const peg$c66 = "${";
408
+ const peg$c67 = "~";
409
+ const peg$c68 = "await";
410
+ const peg$c69 = "typeof";
411
+ const peg$c70 = "void";
410
412
 
411
413
  const peg$r0 = /^[^\/>\t\n\r]/;
412
414
  const peg$r1 = /^[0-9]/;
@@ -515,31 +517,33 @@ function peg$parse(input, options) {
515
517
  const peg$e88 = peg$classExpectation(["/", "\n", "\r"], true, false, false);
516
518
  const peg$e89 = peg$literalExpectation("<=", false);
517
519
  const peg$e90 = peg$literalExpectation(">=", false);
518
- const peg$e91 = peg$literalExpectation("#!", false);
519
- const peg$e92 = peg$classExpectation(["\n", "\r"], true, false, false);
520
- const peg$e93 = peg$literalExpectation("<<", false);
521
- const peg$e94 = peg$literalExpectation(">>>", false);
522
- const peg$e95 = peg$literalExpectation(">>", false);
523
- const peg$e96 = peg$otherExpectation("lambda function");
524
- const peg$e97 = peg$literalExpectation("\u2192", false);
525
- const peg$e98 = peg$literalExpectation("->", false);
526
- const peg$e99 = peg$otherExpectation("single quote string");
527
- const peg$e100 = peg$otherExpectation("string");
528
- const peg$e101 = peg$literalExpectation("${", false);
529
- const peg$e102 = peg$otherExpectation("template document");
530
- const peg$e103 = peg$otherExpectation("template literal");
531
- const peg$e104 = peg$otherExpectation("template substitution");
532
- const peg$e105 = peg$classExpectation(["!", "+"], false, false, false);
533
- const peg$e106 = peg$literalExpectation("~", false);
534
- const peg$e107 = peg$classExpectation(["/", ")", "]", "}"], false, false, false);
535
- const peg$e108 = peg$literalExpectation("await", false);
536
- const peg$e109 = peg$literalExpectation("typeof", false);
537
- const peg$e110 = peg$literalExpectation("void", false);
538
- const peg$e111 = peg$classExpectation(["/", ",", ")", "]", "}"], true, false, false);
539
- const peg$e112 = peg$otherExpectation("slash-separated path");
540
- const peg$e113 = peg$classExpectation([["a", "z"]], false, false, false);
541
- const peg$e114 = peg$classExpectation([["a", "z"], ["0", "9"], ["+", "."]], false, false, false);
542
- const peg$e115 = peg$classExpectation([":"], false, false, false);
520
+ const peg$e91 = peg$literalExpectation("instanceof", false);
521
+ const peg$e92 = peg$literalExpectation("in", false);
522
+ const peg$e93 = peg$literalExpectation("#!", false);
523
+ const peg$e94 = peg$classExpectation(["\n", "\r"], true, false, false);
524
+ const peg$e95 = peg$literalExpectation("<<", false);
525
+ const peg$e96 = peg$literalExpectation(">>>", false);
526
+ const peg$e97 = peg$literalExpectation(">>", false);
527
+ const peg$e98 = peg$otherExpectation("lambda function");
528
+ const peg$e99 = peg$literalExpectation("\u2192", false);
529
+ const peg$e100 = peg$literalExpectation("->", false);
530
+ const peg$e101 = peg$otherExpectation("single quote string");
531
+ const peg$e102 = peg$otherExpectation("string");
532
+ const peg$e103 = peg$literalExpectation("${", false);
533
+ const peg$e104 = peg$otherExpectation("template document");
534
+ const peg$e105 = peg$otherExpectation("template literal");
535
+ const peg$e106 = peg$otherExpectation("template substitution");
536
+ const peg$e107 = peg$classExpectation(["!", "+"], false, false, false);
537
+ const peg$e108 = peg$literalExpectation("~", false);
538
+ const peg$e109 = peg$classExpectation(["/", ")", "]", "}"], false, false, false);
539
+ const peg$e110 = peg$literalExpectation("await", false);
540
+ const peg$e111 = peg$literalExpectation("typeof", false);
541
+ const peg$e112 = peg$literalExpectation("void", false);
542
+ const peg$e113 = peg$classExpectation(["/", ",", ")", "]", "}"], true, false, false);
543
+ const peg$e114 = peg$otherExpectation("slash-separated path");
544
+ const peg$e115 = peg$classExpectation([["a", "z"]], false, false, false);
545
+ const peg$e116 = peg$classExpectation([["a", "z"], ["0", "9"], ["+", "."]], false, false, false);
546
+ const peg$e117 = peg$classExpectation([":"], false, false, false);
543
547
 
544
548
  function peg$f0() {
545
549
  return null;
@@ -5209,6 +5213,24 @@ function peg$parse(input, options) {
5209
5213
  s0 = peg$FAILED;
5210
5214
  if (peg$silentFails === 0) { peg$fail(peg$e3); }
5211
5215
  }
5216
+ if (s0 === peg$FAILED) {
5217
+ if (input.substr(peg$currPos, 10) === peg$c58) {
5218
+ s0 = peg$c58;
5219
+ peg$currPos += 10;
5220
+ } else {
5221
+ s0 = peg$FAILED;
5222
+ if (peg$silentFails === 0) { peg$fail(peg$e91); }
5223
+ }
5224
+ if (s0 === peg$FAILED) {
5225
+ if (input.substr(peg$currPos, 2) === peg$c59) {
5226
+ s0 = peg$c59;
5227
+ peg$currPos += 2;
5228
+ } else {
5229
+ s0 = peg$FAILED;
5230
+ if (peg$silentFails === 0) { peg$fail(peg$e92); }
5231
+ }
5232
+ }
5233
+ }
5212
5234
  }
5213
5235
  }
5214
5236
  }
@@ -5254,12 +5276,12 @@ function peg$parse(input, options) {
5254
5276
  let s0, s1, s2, s3;
5255
5277
 
5256
5278
  s0 = peg$currPos;
5257
- if (input.substr(peg$currPos, 2) === peg$c58) {
5258
- s1 = peg$c58;
5279
+ if (input.substr(peg$currPos, 2) === peg$c60) {
5280
+ s1 = peg$c60;
5259
5281
  peg$currPos += 2;
5260
5282
  } else {
5261
5283
  s1 = peg$FAILED;
5262
- if (peg$silentFails === 0) { peg$fail(peg$e91); }
5284
+ if (peg$silentFails === 0) { peg$fail(peg$e93); }
5263
5285
  }
5264
5286
  if (s1 !== peg$FAILED) {
5265
5287
  s2 = [];
@@ -5268,7 +5290,7 @@ function peg$parse(input, options) {
5268
5290
  peg$currPos++;
5269
5291
  } else {
5270
5292
  s3 = peg$FAILED;
5271
- if (peg$silentFails === 0) { peg$fail(peg$e92); }
5293
+ if (peg$silentFails === 0) { peg$fail(peg$e94); }
5272
5294
  }
5273
5295
  while (s3 !== peg$FAILED) {
5274
5296
  s2.push(s3);
@@ -5277,7 +5299,7 @@ function peg$parse(input, options) {
5277
5299
  peg$currPos++;
5278
5300
  } else {
5279
5301
  s3 = peg$FAILED;
5280
- if (peg$silentFails === 0) { peg$fail(peg$e92); }
5302
+ if (peg$silentFails === 0) { peg$fail(peg$e94); }
5281
5303
  }
5282
5304
  }
5283
5305
  peg$savedPos = s0;
@@ -5359,28 +5381,28 @@ function peg$parse(input, options) {
5359
5381
  function peg$parseshiftOperator() {
5360
5382
  let s0;
5361
5383
 
5362
- if (input.substr(peg$currPos, 2) === peg$c59) {
5363
- s0 = peg$c59;
5384
+ if (input.substr(peg$currPos, 2) === peg$c61) {
5385
+ s0 = peg$c61;
5364
5386
  peg$currPos += 2;
5365
5387
  } else {
5366
5388
  s0 = peg$FAILED;
5367
- if (peg$silentFails === 0) { peg$fail(peg$e93); }
5389
+ if (peg$silentFails === 0) { peg$fail(peg$e95); }
5368
5390
  }
5369
5391
  if (s0 === peg$FAILED) {
5370
- if (input.substr(peg$currPos, 3) === peg$c60) {
5371
- s0 = peg$c60;
5392
+ if (input.substr(peg$currPos, 3) === peg$c62) {
5393
+ s0 = peg$c62;
5372
5394
  peg$currPos += 3;
5373
5395
  } else {
5374
5396
  s0 = peg$FAILED;
5375
- if (peg$silentFails === 0) { peg$fail(peg$e94); }
5397
+ if (peg$silentFails === 0) { peg$fail(peg$e96); }
5376
5398
  }
5377
5399
  if (s0 === peg$FAILED) {
5378
- if (input.substr(peg$currPos, 2) === peg$c61) {
5379
- s0 = peg$c61;
5400
+ if (input.substr(peg$currPos, 2) === peg$c63) {
5401
+ s0 = peg$c63;
5380
5402
  peg$currPos += 2;
5381
5403
  } else {
5382
5404
  s0 = peg$FAILED;
5383
- if (peg$silentFails === 0) { peg$fail(peg$e95); }
5405
+ if (peg$silentFails === 0) { peg$fail(peg$e97); }
5384
5406
  }
5385
5407
  }
5386
5408
  }
@@ -5450,7 +5472,7 @@ function peg$parse(input, options) {
5450
5472
  peg$silentFails--;
5451
5473
  if (s0 === peg$FAILED) {
5452
5474
  s1 = peg$FAILED;
5453
- if (peg$silentFails === 0) { peg$fail(peg$e96); }
5475
+ if (peg$silentFails === 0) { peg$fail(peg$e98); }
5454
5476
  }
5455
5477
 
5456
5478
  return s0;
@@ -5460,19 +5482,19 @@ function peg$parse(input, options) {
5460
5482
  let s0;
5461
5483
 
5462
5484
  if (input.charCodeAt(peg$currPos) === 8594) {
5463
- s0 = peg$c62;
5485
+ s0 = peg$c64;
5464
5486
  peg$currPos++;
5465
5487
  } else {
5466
5488
  s0 = peg$FAILED;
5467
- if (peg$silentFails === 0) { peg$fail(peg$e97); }
5489
+ if (peg$silentFails === 0) { peg$fail(peg$e99); }
5468
5490
  }
5469
5491
  if (s0 === peg$FAILED) {
5470
- if (input.substr(peg$currPos, 2) === peg$c63) {
5471
- s0 = peg$c63;
5492
+ if (input.substr(peg$currPos, 2) === peg$c65) {
5493
+ s0 = peg$c65;
5472
5494
  peg$currPos += 2;
5473
5495
  } else {
5474
5496
  s0 = peg$FAILED;
5475
- if (peg$silentFails === 0) { peg$fail(peg$e98); }
5497
+ if (peg$silentFails === 0) { peg$fail(peg$e100); }
5476
5498
  }
5477
5499
  }
5478
5500
 
@@ -5497,7 +5519,7 @@ function peg$parse(input, options) {
5497
5519
  peg$currPos++;
5498
5520
  } else {
5499
5521
  s3 = peg$FAILED;
5500
- if (peg$silentFails === 0) { peg$fail(peg$e92); }
5522
+ if (peg$silentFails === 0) { peg$fail(peg$e94); }
5501
5523
  }
5502
5524
  while (s3 !== peg$FAILED) {
5503
5525
  s2.push(s3);
@@ -5506,7 +5528,7 @@ function peg$parse(input, options) {
5506
5528
  peg$currPos++;
5507
5529
  } else {
5508
5530
  s3 = peg$FAILED;
5509
- if (peg$silentFails === 0) { peg$fail(peg$e92); }
5531
+ if (peg$silentFails === 0) { peg$fail(peg$e94); }
5510
5532
  }
5511
5533
  }
5512
5534
  peg$savedPos = s0;
@@ -5553,7 +5575,7 @@ function peg$parse(input, options) {
5553
5575
  peg$silentFails--;
5554
5576
  if (s0 === peg$FAILED) {
5555
5577
  s1 = peg$FAILED;
5556
- if (peg$silentFails === 0) { peg$fail(peg$e99); }
5578
+ if (peg$silentFails === 0) { peg$fail(peg$e101); }
5557
5579
  }
5558
5580
 
5559
5581
  return s0;
@@ -5726,7 +5748,7 @@ function peg$parse(input, options) {
5726
5748
  peg$silentFails--;
5727
5749
  if (s0 === peg$FAILED) {
5728
5750
  s1 = peg$FAILED;
5729
- if (peg$silentFails === 0) { peg$fail(peg$e100); }
5751
+ if (peg$silentFails === 0) { peg$fail(peg$e102); }
5730
5752
  }
5731
5753
 
5732
5754
  return s0;
@@ -5775,12 +5797,12 @@ function peg$parse(input, options) {
5775
5797
  s0 = peg$currPos;
5776
5798
  s1 = peg$currPos;
5777
5799
  peg$silentFails++;
5778
- if (input.substr(peg$currPos, 2) === peg$c64) {
5779
- s2 = peg$c64;
5800
+ if (input.substr(peg$currPos, 2) === peg$c66) {
5801
+ s2 = peg$c66;
5780
5802
  peg$currPos += 2;
5781
5803
  } else {
5782
5804
  s2 = peg$FAILED;
5783
- if (peg$silentFails === 0) { peg$fail(peg$e101); }
5805
+ if (peg$silentFails === 0) { peg$fail(peg$e103); }
5784
5806
  }
5785
5807
  peg$silentFails--;
5786
5808
  if (s2 === peg$FAILED) {
@@ -5861,7 +5883,7 @@ function peg$parse(input, options) {
5861
5883
  peg$silentFails--;
5862
5884
  if (s0 === peg$FAILED) {
5863
5885
  s1 = peg$FAILED;
5864
- if (peg$silentFails === 0) { peg$fail(peg$e102); }
5886
+ if (peg$silentFails === 0) { peg$fail(peg$e104); }
5865
5887
  }
5866
5888
 
5867
5889
  return s0;
@@ -5920,7 +5942,7 @@ function peg$parse(input, options) {
5920
5942
  peg$silentFails--;
5921
5943
  if (s0 === peg$FAILED) {
5922
5944
  s1 = peg$FAILED;
5923
- if (peg$silentFails === 0) { peg$fail(peg$e103); }
5945
+ if (peg$silentFails === 0) { peg$fail(peg$e105); }
5924
5946
  }
5925
5947
 
5926
5948
  return s0;
@@ -5940,12 +5962,12 @@ function peg$parse(input, options) {
5940
5962
  if (peg$silentFails === 0) { peg$fail(peg$e42); }
5941
5963
  }
5942
5964
  if (s2 === peg$FAILED) {
5943
- if (input.substr(peg$currPos, 2) === peg$c64) {
5944
- s2 = peg$c64;
5965
+ if (input.substr(peg$currPos, 2) === peg$c66) {
5966
+ s2 = peg$c66;
5945
5967
  peg$currPos += 2;
5946
5968
  } else {
5947
5969
  s2 = peg$FAILED;
5948
- if (peg$silentFails === 0) { peg$fail(peg$e101); }
5970
+ if (peg$silentFails === 0) { peg$fail(peg$e103); }
5949
5971
  }
5950
5972
  }
5951
5973
  peg$silentFails--;
@@ -5993,12 +6015,12 @@ function peg$parse(input, options) {
5993
6015
 
5994
6016
  peg$silentFails++;
5995
6017
  s0 = peg$currPos;
5996
- if (input.substr(peg$currPos, 2) === peg$c64) {
5997
- s1 = peg$c64;
6018
+ if (input.substr(peg$currPos, 2) === peg$c66) {
6019
+ s1 = peg$c66;
5998
6020
  peg$currPos += 2;
5999
6021
  } else {
6000
6022
  s1 = peg$FAILED;
6001
- if (peg$silentFails === 0) { peg$fail(peg$e101); }
6023
+ if (peg$silentFails === 0) { peg$fail(peg$e103); }
6002
6024
  }
6003
6025
  if (s1 !== peg$FAILED) {
6004
6026
  s2 = peg$parseexpectExpression();
@@ -6028,7 +6050,7 @@ function peg$parse(input, options) {
6028
6050
  peg$silentFails--;
6029
6051
  if (s0 === peg$FAILED) {
6030
6052
  s1 = peg$FAILED;
6031
- if (peg$silentFails === 0) { peg$fail(peg$e104); }
6053
+ if (peg$silentFails === 0) { peg$fail(peg$e106); }
6032
6054
  }
6033
6055
 
6034
6056
  return s0;
@@ -6085,16 +6107,16 @@ function peg$parse(input, options) {
6085
6107
  peg$currPos++;
6086
6108
  } else {
6087
6109
  s0 = peg$FAILED;
6088
- if (peg$silentFails === 0) { peg$fail(peg$e105); }
6110
+ if (peg$silentFails === 0) { peg$fail(peg$e107); }
6089
6111
  }
6090
6112
  if (s0 === peg$FAILED) {
6091
6113
  s0 = peg$currPos;
6092
6114
  if (input.charCodeAt(peg$currPos) === 126) {
6093
- s1 = peg$c65;
6115
+ s1 = peg$c67;
6094
6116
  peg$currPos++;
6095
6117
  } else {
6096
6118
  s1 = peg$FAILED;
6097
- if (peg$silentFails === 0) { peg$fail(peg$e106); }
6119
+ if (peg$silentFails === 0) { peg$fail(peg$e108); }
6098
6120
  }
6099
6121
  if (s1 !== peg$FAILED) {
6100
6122
  s2 = peg$currPos;
@@ -6104,7 +6126,7 @@ function peg$parse(input, options) {
6104
6126
  peg$currPos++;
6105
6127
  } else {
6106
6128
  s3 = peg$FAILED;
6107
- if (peg$silentFails === 0) { peg$fail(peg$e107); }
6129
+ if (peg$silentFails === 0) { peg$fail(peg$e109); }
6108
6130
  }
6109
6131
  peg$silentFails--;
6110
6132
  if (s3 === peg$FAILED) {
@@ -6127,12 +6149,12 @@ function peg$parse(input, options) {
6127
6149
  s0 = peg$parseminus();
6128
6150
  if (s0 === peg$FAILED) {
6129
6151
  s0 = peg$currPos;
6130
- if (input.substr(peg$currPos, 5) === peg$c66) {
6131
- s1 = peg$c66;
6152
+ if (input.substr(peg$currPos, 5) === peg$c68) {
6153
+ s1 = peg$c68;
6132
6154
  peg$currPos += 5;
6133
6155
  } else {
6134
6156
  s1 = peg$FAILED;
6135
- if (peg$silentFails === 0) { peg$fail(peg$e108); }
6157
+ if (peg$silentFails === 0) { peg$fail(peg$e110); }
6136
6158
  }
6137
6159
  if (s1 !== peg$FAILED) {
6138
6160
  s2 = peg$currPos;
@@ -6157,12 +6179,12 @@ function peg$parse(input, options) {
6157
6179
  }
6158
6180
  if (s0 === peg$FAILED) {
6159
6181
  s0 = peg$currPos;
6160
- if (input.substr(peg$currPos, 6) === peg$c67) {
6161
- s1 = peg$c67;
6182
+ if (input.substr(peg$currPos, 6) === peg$c69) {
6183
+ s1 = peg$c69;
6162
6184
  peg$currPos += 6;
6163
6185
  } else {
6164
6186
  s1 = peg$FAILED;
6165
- if (peg$silentFails === 0) { peg$fail(peg$e109); }
6187
+ if (peg$silentFails === 0) { peg$fail(peg$e111); }
6166
6188
  }
6167
6189
  if (s1 !== peg$FAILED) {
6168
6190
  s2 = peg$currPos;
@@ -6187,12 +6209,12 @@ function peg$parse(input, options) {
6187
6209
  }
6188
6210
  if (s0 === peg$FAILED) {
6189
6211
  s0 = peg$currPos;
6190
- if (input.substr(peg$currPos, 4) === peg$c68) {
6191
- s1 = peg$c68;
6212
+ if (input.substr(peg$currPos, 4) === peg$c70) {
6213
+ s1 = peg$c70;
6192
6214
  peg$currPos += 4;
6193
6215
  } else {
6194
6216
  s1 = peg$FAILED;
6195
- if (peg$silentFails === 0) { peg$fail(peg$e110); }
6217
+ if (peg$silentFails === 0) { peg$fail(peg$e112); }
6196
6218
  }
6197
6219
  if (s1 !== peg$FAILED) {
6198
6220
  s2 = peg$currPos;
@@ -6372,7 +6394,7 @@ function peg$parse(input, options) {
6372
6394
  peg$currPos++;
6373
6395
  } else {
6374
6396
  s1 = peg$FAILED;
6375
- if (peg$silentFails === 0) { peg$fail(peg$e111); }
6397
+ if (peg$silentFails === 0) { peg$fail(peg$e113); }
6376
6398
  }
6377
6399
  if (s1 !== peg$FAILED) {
6378
6400
  s2 = peg$currPos;
@@ -6435,7 +6457,7 @@ function peg$parse(input, options) {
6435
6457
  peg$silentFails--;
6436
6458
  if (s0 === peg$FAILED) {
6437
6459
  s1 = peg$FAILED;
6438
- if (peg$silentFails === 0) { peg$fail(peg$e112); }
6460
+ if (peg$silentFails === 0) { peg$fail(peg$e114); }
6439
6461
  }
6440
6462
 
6441
6463
  return s0;
@@ -6450,7 +6472,7 @@ function peg$parse(input, options) {
6450
6472
  peg$currPos++;
6451
6473
  } else {
6452
6474
  s1 = peg$FAILED;
6453
- if (peg$silentFails === 0) { peg$fail(peg$e113); }
6475
+ if (peg$silentFails === 0) { peg$fail(peg$e115); }
6454
6476
  }
6455
6477
  if (s1 !== peg$FAILED) {
6456
6478
  s2 = [];
@@ -6459,7 +6481,7 @@ function peg$parse(input, options) {
6459
6481
  peg$currPos++;
6460
6482
  } else {
6461
6483
  s3 = peg$FAILED;
6462
- if (peg$silentFails === 0) { peg$fail(peg$e114); }
6484
+ if (peg$silentFails === 0) { peg$fail(peg$e116); }
6463
6485
  }
6464
6486
  while (s3 !== peg$FAILED) {
6465
6487
  s2.push(s3);
@@ -6468,7 +6490,7 @@ function peg$parse(input, options) {
6468
6490
  peg$currPos++;
6469
6491
  } else {
6470
6492
  s3 = peg$FAILED;
6471
- if (peg$silentFails === 0) { peg$fail(peg$e114); }
6493
+ if (peg$silentFails === 0) { peg$fail(peg$e116); }
6472
6494
  }
6473
6495
  }
6474
6496
  s3 = input.charAt(peg$currPos);
@@ -6476,7 +6498,7 @@ function peg$parse(input, options) {
6476
6498
  peg$currPos++;
6477
6499
  } else {
6478
6500
  s3 = peg$FAILED;
6479
- if (peg$silentFails === 0) { peg$fail(peg$e115); }
6501
+ if (peg$silentFails === 0) { peg$fail(peg$e117); }
6480
6502
  }
6481
6503
  if (s3 !== peg$FAILED) {
6482
6504
  peg$savedPos = s0;
@@ -142,6 +142,8 @@ export function makeBinaryOperation(left, [operatorToken, right]) {
142
142
  ">>>": ops.shiftRightUnsigned,
143
143
  "^": ops.bitwiseXor,
144
144
  "|": ops.bitwiseOr,
145
+ instanceof: ops.instanceOf,
146
+ in: ops.inOperator,
145
147
  };
146
148
  const op = operators[operatorToken];
147
149
 
@@ -3,11 +3,11 @@ import {
3
3
  isUnpackable,
4
4
  symbols,
5
5
  toString,
6
+ Tree,
6
7
  } from "@weborigami/async-tree";
7
8
  import * as YAMLModule from "yaml";
8
9
  import * as compile from "../compiler/compile.js";
9
10
  import projectGlobals from "../project/projectGlobals.js";
10
- import * as expressionFunction from "../runtime/expressionFunction.js";
11
11
  import getSource from "./getSource.js";
12
12
 
13
13
  // The "yaml" package doesn't seem to provide a default export that the browser can
@@ -15,6 +15,17 @@ import getSource from "./getSource.js";
15
15
  // @ts-ignore
16
16
  const YAML = YAMLModule.default ?? YAMLModule.YAML;
17
17
 
18
+ // True if we encountered !ori or !ori.call tags while parsing
19
+ let hasOriTags = false;
20
+
21
+ // When processing the !ori tag, the YAML parser will convert our compiler
22
+ // errors into YAML syntax errors. We track the last compiler error so we can
23
+ // re-throw it.
24
+ let lastCompilerError = null;
25
+
26
+ // The source of the last Origami line parsed in a YAML file, used for errors
27
+ let source;
28
+
18
29
  /**
19
30
  * A YAML file
20
31
  *
@@ -31,72 +42,145 @@ export default {
31
42
  throw new Error("Tried to parse something as YAML but it wasn't text.");
32
43
  }
33
44
  const parent = getParent(packed, options);
34
- const oriCallTag = await oriCallTagForParent(parent, options);
35
- const oriTag = await oriTagForParent(parent, options);
45
+ const oriCallTag = await oriCallTagForParent(parent, options, yaml);
46
+ const oriTag = await oriTagForParent(parent, options, yaml);
47
+ hasOriTags = false; // Haven't seen any yet
48
+
49
+ let data;
36
50
  // YAML parser is sync, but top-level !ori or !ori.call tags will return a
37
51
  // promise.
38
- // @ts-ignore TypeScript complains customTags isn't valid here but it is.
39
- const data = await YAML.parse(yaml, {
40
- customTags: [oriCallTag, oriTag],
41
- });
52
+ try {
53
+ // @ts-ignore TypeScript complains customTags isn't valid here but it is.
54
+ data = YAML.parse(yaml, {
55
+ customTags: [oriCallTag, oriTag],
56
+ });
57
+ } catch (/** @type {any} */ error) {
58
+ if (error.name === "SyntaxError") {
59
+ // One of our compiler errors, probably thrown by !ori.call tag
60
+ throw error;
61
+ }
62
+ const errorText = yaml.slice(error.pos[0], error.pos[1]);
63
+ const isOriError = errorText === "!ori" || errorText === "!ori.call";
64
+ if (isOriError && lastCompilerError) {
65
+ // Error is in an Origami tag, probably throw by !ori tag. Find the
66
+ // position of the Origami source in the YAML text.
67
+ let offset = error.pos[0] + errorText.length;
68
+ while (/\s/.test(yaml[offset])) {
69
+ offset++;
70
+ }
71
+ lastCompilerError.location.source.offset = offset;
72
+ throw lastCompilerError;
73
+ } else {
74
+ // Some other YAML parsing error
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ if (data instanceof Promise) {
80
+ // Top-level !ori or !ori.call tag returned a promise
81
+ data = await data;
82
+ }
83
+
84
+ if (hasOriTags) {
85
+ // Resolve any promises in the data.
86
+ data = await Tree.plain(data);
87
+ }
88
+
42
89
  if (data && typeof data === "object" && Object.isExtensible(data)) {
43
90
  Object.defineProperty(data, symbols.deep, {
44
91
  enumerable: false,
45
92
  value: true,
46
93
  });
47
94
  }
95
+
48
96
  return data;
49
97
  },
50
98
  };
51
99
 
52
- async function oriCallTagForParent(parent, options) {
100
+ async function oriCallTagForParent(parent, options, yaml) {
53
101
  const globals = await projectGlobals();
54
102
  return {
55
103
  collection: "seq",
56
104
 
57
105
  tag: "!ori.call",
58
106
 
59
- identify: (value) => false,
60
-
61
- async resolve(value) {
107
+ resolve(value) {
108
+ hasOriTags = true;
62
109
  /** @type {any[]} */
63
110
  const args = typeof value?.toJSON === "function" ? value.toJSON() : value;
64
111
 
65
112
  // First arg is Origami source
66
113
  const text = args.shift();
67
- const source = getSource(text, options);
68
-
69
- const codeFn = compile.expression(source, {
70
- globals,
71
- parent,
72
- });
114
+ source = getSource(text, options);
73
115
 
74
- // Evaluate the code to get a function
75
- let fn = await codeFn.call(parent);
116
+ // Offset the source position to account for its location in YAML text
117
+ source.context = yaml;
118
+ const firstItem = value.items[0];
119
+ source.offset = firstItem.range[0];
120
+ if (
121
+ firstItem.type === "QUOTE_DOUBLE" ||
122
+ firstItem.type === "QUOTE_SINGLE"
123
+ ) {
124
+ // Account for opening quote
125
+ source.offset += 1;
126
+ }
76
127
 
77
- // Call the function with the rest of the args
78
- if (isUnpackable(fn)) {
79
- fn = await fn.unpack();
128
+ lastCompilerError = null;
129
+ let codeFn;
130
+ try {
131
+ codeFn = compile.expression(source, {
132
+ globals,
133
+ parent,
134
+ });
135
+ } catch (error) {
136
+ lastCompilerError = error;
137
+ throw error;
80
138
  }
81
139
 
82
- return fn.call(null, ...args);
140
+ // Return a promise for the code's evaluation. If we instead define
141
+ // resolve() as async, the catch block in unpack() won't catch Origami
142
+ // parse errors.
143
+ return new Promise(async (resolve) => {
144
+ // Evaluate the code to get a function
145
+ let fn = await codeFn.call(parent);
146
+
147
+ // Call the function with the rest of the args
148
+ if (isUnpackable(fn)) {
149
+ fn = await fn.unpack();
150
+ }
151
+
152
+ // Resolve any promise args
153
+ const resolvedArgs = await Promise.all(args);
154
+
155
+ const result = await fn.call(null, ...resolvedArgs);
156
+ resolve(result);
157
+ });
83
158
  },
84
159
  };
85
160
  }
86
161
 
87
162
  // Define the !ori tag for YAML parsing. This will run in the context of the
88
163
  // supplied parent.
89
- async function oriTagForParent(parent, options) {
164
+ async function oriTagForParent(parent, options, yaml) {
90
165
  const globals = await projectGlobals();
91
166
  return {
92
- identify: expressionFunction.isExpressionFunction,
93
-
94
167
  resolve(text) {
95
- const source = getSource(text, options);
96
- const fn = compile.expression(source, {
97
- globals,
98
- parent,
99
- });
168
+ hasOriTags = true;
169
+ source = getSource(text, options);
170
+ source.context = yaml;
171
+
172
+ lastCompilerError = null;
173
+ let fn;
174
+ try {
175
+ fn = compile.expression(source, {
176
+ globals,
177
+ parent,
178
+ });
179
+ } catch (error) {
180
+ lastCompilerError = error;
181
+ throw error;
182
+ }
183
+
100
184
  return fn.call(parent);
101
185
  },
102
186
 
@@ -12,7 +12,7 @@ import path from "node:path";
12
12
  * Fetch API
13
13
  * URL API
14
14
  */
15
- const globals = bindStaticMethodsForGlobals({
15
+ const globals = {
16
16
  AbortController,
17
17
  AbortSignal,
18
18
  AggregateError,
@@ -152,7 +152,7 @@ const globals = bindStaticMethodsForGlobals({
152
152
  // Special cases
153
153
  fetch: fetchWrapper,
154
154
  import: importWrapper,
155
- });
155
+ };
156
156
 
157
157
  // Give access to our own custom globals as `globalThis`
158
158
  Object.defineProperty(globals, "globalThis", {
@@ -190,64 +190,4 @@ async function importWrapper(modulePath) {
190
190
  }
191
191
  importWrapper.containerAsTarget = true;
192
192
 
193
- /**
194
- * Some JavaScript globals like Promise have static methods like Promise.all
195
- * verify that the call target is the class. This creates an issue because the
196
- * Origami evaluate() function calls all functions with the evaluation context
197
- * -- the tree in which the code is running -- as the call target.
198
- *
199
- * This function works around the problem. If the indicated object has no static
200
- * methods, it's returned as is. If it does have static methods, this returns an
201
- * extension of the object that overrides the static methods with ones that are
202
- * bound to the object.
203
- */
204
- function bindStaticMethods(obj) {
205
- if (typeof obj !== "function" && (typeof obj !== "object" || obj === null)) {
206
- // Something like `NaN` or `null`
207
- return obj;
208
- }
209
-
210
- const staticMethodDescriptors = Object.entries(
211
- Object.getOwnPropertyDescriptors(obj)
212
- )
213
- .filter(([key, descriptor]) => descriptor.value instanceof Function)
214
- .map(([key, descriptor]) => [
215
- key,
216
- {
217
- ...descriptor,
218
- value: descriptor.value.bind(obj),
219
- },
220
- ]);
221
- if (staticMethodDescriptors.length === 0) {
222
- // No static methods
223
- return obj;
224
- }
225
-
226
- let extended;
227
- if (typeof obj === "object" || !obj.prototype) {
228
- // A regular object or an oddball like Proxy with no prototype
229
- extended = Object.create(obj);
230
- } else {
231
- // A function, possibly a constructor called with or without `new`
232
- /** @this {any} */
233
- extended = function (...args) {
234
- const calledWithNew = this instanceof extended;
235
- return calledWithNew ? new obj(...args) : obj(...args);
236
- };
237
- }
238
-
239
- Object.defineProperties(
240
- extended,
241
- Object.fromEntries(staticMethodDescriptors)
242
- );
243
-
244
- return extended;
245
- }
246
-
247
- function bindStaticMethodsForGlobals(objects) {
248
- const entries = Object.entries(objects);
249
- const bound = entries.map(([key, value]) => [key, bindStaticMethods(value)]);
250
- return Object.fromEntries(bound);
251
- }
252
-
253
193
  export default globals;
@@ -9,6 +9,9 @@ import { pathFromKeys } from "@weborigami/async-tree";
9
9
  */
10
10
  export default function constructHref(protocol, host, ...keys) {
11
11
  const path = pathFromKeys(keys);
12
+ if (host.endsWith("/")) {
13
+ host = host.slice(0, -1);
14
+ }
12
15
  let href = [host, path].join("/");
13
16
  if (!href.startsWith(protocol)) {
14
17
  if (!href.startsWith("//")) {
@@ -0,0 +1,13 @@
1
+ import { ExplorableSiteMap } from "@weborigami/async-tree";
2
+ import constructSiteTree from "./constructSiteTree.js";
3
+
4
+ /**
5
+ * A site tree with JSON Keys via HTTP.
6
+ *
7
+ *
8
+ * @param {string} host
9
+ * @param {...string} keys
10
+ */
11
+ export default function explorehttp(host, ...keys) {
12
+ return constructSiteTree("http:", ExplorableSiteMap, host, ...keys);
13
+ }
@@ -2,6 +2,7 @@ import * as protocols from "./protocols.js";
2
2
 
3
3
  export default {
4
4
  "explore:": protocols.explore,
5
+ "explorehttp:": protocols.explorehttp,
5
6
  "files:": protocols.files,
6
7
  "http:": protocols.http,
7
8
  "https:": protocols.https,
@@ -1,4 +1,5 @@
1
1
  export { default as explore } from "./explore.js";
2
+ export { default as explorehttp } from "./explorehttp.js";
2
3
  export { default as files } from "./files.js";
3
4
  export { default as http } from "./http.js";
4
5
  export { default as https } from "./https.js";
@@ -144,9 +144,22 @@ export function maybeOrigamiSourceCode(text) {
144
144
  // Return user-friendly line information for the error location
145
145
  function lineInfo(location) {
146
146
  let { source, start } = location;
147
- // Adjust line number with offset if present (for example, if the code is in
148
- // an Origami template document with front matter that was stripped)
149
- let line = start.line + (source.offset ?? 0);
147
+
148
+ let line;
149
+ let column;
150
+ if (source.offset && source.context) {
151
+ // Account for source code that was offset within a larger document
152
+ const offset = source.offset + start.offset;
153
+ // Calculate line and column from offset
154
+ const textUpToOffset = source.context.slice(0, offset);
155
+ const lines = textUpToOffset.split("\n");
156
+ line = lines.length;
157
+ column = lines[lines.length - 1].length + 1;
158
+ } else {
159
+ // Use indicated start location as is
160
+ line = start.line;
161
+ column = start.column;
162
+ }
150
163
 
151
164
  if (typeof source === "object" && source.url) {
152
165
  const { url } = source;
@@ -162,10 +175,10 @@ function lineInfo(location) {
162
175
  // Not a file: URL, use as is
163
176
  fileRef = url.href;
164
177
  }
165
- return `\n at ${fileRef}:${line}:${start.column}`;
178
+ return `\n at ${fileRef}:${line}:${column}`;
166
179
  } else if (source.text.includes("\n")) {
167
180
  // Don't know the URL, but has multiple lines so add line number
168
- return `\n at line ${line}, column ${start.column}`;
181
+ return `\n at line ${line}, column ${column}`;
169
182
  } else {
170
183
  return "";
171
184
  }
@@ -181,6 +181,11 @@ export async function homeDirectory(...keys) {
181
181
  }
182
182
  addOpLabel(homeDirectory, "«ops.homeDirectory»");
183
183
 
184
+ export function inOperator(a, b) {
185
+ return a in b;
186
+ }
187
+ addOpLabel(inOperator, "«ops.inOperator»");
188
+
184
189
  /**
185
190
  * Given the tree currently be using as the context for the runtime, walk up the
186
191
  * parent chain `depth` levels and return that tree.
@@ -203,6 +208,11 @@ export async function inherited(depth, state) {
203
208
  addOpLabel(inherited, "«ops.inherited»");
204
209
  inherited.needsState = true;
205
210
 
211
+ export function instanceOf(a, b) {
212
+ return a instanceof b;
213
+ }
214
+ addOpLabel(instanceOf, "«ops.instanceOf»");
215
+
206
216
  /**
207
217
  * Return a function that will invoke the given code.
208
218
  *
@@ -1,4 +1,3 @@
1
- import { Tree } from "@weborigami/async-tree";
2
1
  import assert from "node:assert";
3
2
  import { describe, test } from "node:test";
4
3
  import yaml_handler from "../../src/handlers/yaml_handler.js";
@@ -22,8 +21,7 @@ message: Hello
22
21
  answer: !ori 1 + 1
23
22
  `;
24
23
  const data = await yaml_handler.unpack(text);
25
- const plain = await Tree.plain(data);
26
- assert.deepEqual(plain, {
24
+ assert.deepEqual(data, {
27
25
  message: "Hello",
28
26
  answer: 2,
29
27
  });
@@ -38,8 +36,7 @@ answer: !ori.call
38
36
  - 3
39
37
  `;
40
38
  const data = await yaml_handler.unpack(text);
41
- const plain = await Tree.plain(data);
42
- assert.deepEqual(plain, {
39
+ assert.deepEqual(data, {
43
40
  message: "Hello",
44
41
  answer: 5,
45
42
  });
@@ -3,19 +3,25 @@ import { describe, test } from "node:test";
3
3
  import jsGlobals from "../../src/project/jsGlobals.js";
4
4
 
5
5
  describe("jsGlobals", () => {
6
- test("can invoke static methods", async () => {
7
- const { Promise } = jsGlobals;
8
- const { all } = Promise;
9
- const result = (
10
- await all(["fruit", "computer", "park"].map((item) => `Apple ${item}`))
11
- ).join(", ");
12
- assert.equal(result, "Apple fruit, Apple computer, Apple park");
6
+ test("can invoke finicky methods like Promise.all that check their receiver", async () => {
7
+ const value = await jsGlobals.Promise.all([Promise.resolve("hi")]);
8
+ assert.equal(value, "hi");
13
9
  });
14
10
 
15
- test("can invoke a method on a static method", () => {
11
+ test("can invoke a static method on a global", () => {
16
12
  const { Math } = jsGlobals;
17
13
  const a = [1, 3, 2];
18
14
  const b = Math.max.apply(null, a);
19
15
  assert.equal(b, 3);
20
16
  });
17
+
18
+ test("can invoke a global constructor", async () => {
19
+ const { Number: fixture } = jsGlobals;
20
+ // Without `new`
21
+ const instance1 = fixture(5);
22
+ assert.equal(instance1, 5);
23
+ // With `new`
24
+ const instance = new fixture();
25
+ assert(instance instanceof Number);
26
+ });
21
27
  });
@@ -155,6 +155,14 @@ describe("ops", () => {
155
155
  assert(ops.greaterThanOrEqual("ab", "aa"));
156
156
  });
157
157
 
158
+ test("ops.inOperator returns true if a is in object b", () => {
159
+ assert.strictEqual(ops.inOperator("a", { a: 1, b: 2 }), true);
160
+ assert.strictEqual(ops.inOperator("c", { a: 1, b: 2 }), false);
161
+ const arr = [0, 0, 0];
162
+ assert.strictEqual(ops.inOperator(1, arr), true);
163
+ assert.strictEqual(ops.inOperator(3, arr), false);
164
+ });
165
+
158
166
  test("ops.inherited walks up the object parent chain", async () => {
159
167
  const tree = new ObjectMap(
160
168
  {
@@ -168,6 +176,16 @@ describe("ops", () => {
168
176
  assert.equal(await ops.inherited(2, { object: b }), tree);
169
177
  });
170
178
 
179
+ test("ops.instanceOf checks prototype chain", () => {
180
+ class Parent {}
181
+ class Child extends Parent {}
182
+ const child = new Child();
183
+ assert.strictEqual(ops.instanceOf(child, Child), true);
184
+ assert.strictEqual(ops.instanceOf(child, Parent), true);
185
+ assert.strictEqual(ops.instanceOf(child, Object), true);
186
+ assert.strictEqual(ops.instanceOf(child, Array), false);
187
+ });
188
+
171
189
  test("ops.lambda defines a function with no inputs", async () => {
172
190
  const code = createCode([ops.lambda, [], [ops.literal, "result"]]);
173
191
  const fn = await evaluate(code);
@@ -1,21 +0,0 @@
1
- import assert from "node:assert";
2
- import { describe, test } from "node:test";
3
- import jsGlobals from "../../src/project/jsGlobals.js";
4
-
5
- describe("jsGlobals", () => {
6
- test("wraps static methods to bind them to defining object", async () => {
7
- const all = jsGlobals.Promise.all;
8
- const value = await all([Promise.resolve("hi")]);
9
- assert.equal(value, "hi");
10
- });
11
-
12
- test("can invoke a global constructor", async () => {
13
- const { Number: fixture } = jsGlobals;
14
- // Without `new`
15
- const instance1 = fixture(5);
16
- assert.equal(instance1, 5);
17
- // With `new`
18
- const instance = new fixture();
19
- assert(instance instanceof Number);
20
- });
21
- });