@weborigami/language 0.5.4 → 0.5.6

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.
Files changed (97) hide show
  1. package/index.ts +16 -6
  2. package/main.js +9 -4
  3. package/package.json +4 -3
  4. package/src/compiler/compile.js +10 -4
  5. package/src/compiler/optimize.js +115 -97
  6. package/src/compiler/origami.pegjs +1 -4
  7. package/src/compiler/parse.js +568 -588
  8. package/src/compiler/parserHelpers.js +3 -3
  9. package/src/handlers/css_handler.js +7 -0
  10. package/src/handlers/csv_handler.js +129 -0
  11. package/src/handlers/handlers.js +33 -0
  12. package/src/handlers/htm_handler.js +2 -0
  13. package/src/handlers/html_handler.js +7 -0
  14. package/src/handlers/jpeg_handler.js +62 -0
  15. package/src/handlers/jpg_handler.js +2 -0
  16. package/src/handlers/js_handler.js +51 -0
  17. package/src/handlers/json_handler.js +26 -0
  18. package/src/handlers/md_handler.js +7 -0
  19. package/src/handlers/mjs_handler.js +2 -0
  20. package/src/handlers/ori_handler.js +47 -0
  21. package/src/handlers/oridocument_handler.js +77 -0
  22. package/src/handlers/parseFrontMatter.js +16 -0
  23. package/src/handlers/ts_handler.js +1 -0
  24. package/src/handlers/txt_handler.js +108 -0
  25. package/src/handlers/wasm_handler.js +15 -0
  26. package/src/handlers/xhtml_handler.js +2 -0
  27. package/src/handlers/yaml_handler.js +33 -0
  28. package/src/handlers/yml_handler.js +2 -0
  29. package/src/project/builtins.js +5 -0
  30. package/src/project/coreGlobals.js +17 -0
  31. package/src/{runtime → project}/jsGlobals.js +3 -1
  32. package/src/project/projectConfig.js +36 -0
  33. package/src/project/projectGlobals.js +19 -0
  34. package/src/project/projectRoot.js +59 -0
  35. package/src/protocols/constructHref.js +20 -0
  36. package/src/protocols/constructSiteTree.js +26 -0
  37. package/src/protocols/explore.js +14 -0
  38. package/src/protocols/fetchAndHandleExtension.js +25 -0
  39. package/src/protocols/files.js +26 -0
  40. package/src/protocols/http.js +15 -0
  41. package/src/protocols/https.js +15 -0
  42. package/src/protocols/httpstree.js +14 -0
  43. package/src/protocols/httptree.js +14 -0
  44. package/src/protocols/node.js +13 -0
  45. package/src/protocols/package.js +67 -0
  46. package/src/protocols/protocolGlobals.js +12 -0
  47. package/src/protocols/protocols.js +8 -0
  48. package/src/runtime/EventTargetMixin.js +1 -1
  49. package/src/runtime/HandleExtensionsTransform.js +3 -12
  50. package/src/runtime/ImportModulesMixin.js +4 -10
  51. package/src/runtime/InvokeFunctionsTransform.js +1 -1
  52. package/src/runtime/errors.js +2 -2
  53. package/src/runtime/evaluate.js +15 -8
  54. package/src/runtime/expressionFunction.js +5 -7
  55. package/src/runtime/expressionObject.js +10 -20
  56. package/src/runtime/functionResultsMap.js +5 -12
  57. package/src/runtime/{handlers.js → handleExtension.js} +14 -12
  58. package/src/runtime/mergeTrees.js +2 -10
  59. package/src/runtime/ops.js +91 -106
  60. package/test/compiler/compile.test.js +20 -19
  61. package/test/compiler/optimize.test.js +60 -25
  62. package/test/compiler/parse.test.js +10 -10
  63. package/test/generator/oriEval.js +4 -5
  64. package/test/handlers/csv.handler.test.js +36 -0
  65. package/test/handlers/fixtures/add.wasm +0 -0
  66. package/test/handlers/fixtures/exif.jpeg +0 -0
  67. package/test/handlers/fixtures/frontMatter.md +5 -0
  68. package/test/handlers/fixtures/list.js +4 -0
  69. package/test/handlers/fixtures/multiple.js +4 -0
  70. package/test/handlers/fixtures/obj.js +3 -0
  71. package/test/handlers/fixtures/site.ori +5 -0
  72. package/test/handlers/fixtures/string.js +1 -0
  73. package/test/handlers/fixtures/tag.yaml +5 -0
  74. package/test/handlers/fixtures/test.ori +9 -0
  75. package/test/handlers/jpeg.handler.test.js +18 -0
  76. package/test/handlers/js.handler.test.js +46 -0
  77. package/test/handlers/json.handler.test.js +14 -0
  78. package/test/handlers/ori.handler.test.js +87 -0
  79. package/test/handlers/oridocument.handler.test.js +68 -0
  80. package/test/handlers/txt.handler.test.js +41 -0
  81. package/test/handlers/wasm.handler.test.js +20 -0
  82. package/test/handlers/yaml.handler.test.js +17 -0
  83. package/test/project/fixtures/withConfig/config.ori +4 -0
  84. package/test/project/fixtures/withConfig/subfolder/greet.js +1 -0
  85. package/test/project/fixtures/withPackageJson/package.json +0 -0
  86. package/test/project/jsGlobals.test.js +21 -0
  87. package/test/project/projectConfig.test.js +28 -0
  88. package/test/project/projectRoot.test.js +40 -0
  89. package/test/protocols/package.test.js +11 -0
  90. package/test/runtime/evaluate.test.js +26 -42
  91. package/test/runtime/expressionObject.test.js +16 -20
  92. package/test/runtime/functionResultsMap.test.js +5 -9
  93. package/test/runtime/{handlers.test.js → handleExtension.test.js} +4 -20
  94. package/test/runtime/jsGlobals.test.js +4 -6
  95. package/test/runtime/mergeTrees.test.js +2 -4
  96. package/test/runtime/ops.test.js +70 -72
  97. package/src/runtime/getHandlers.js +0 -10
@@ -21,7 +21,7 @@ describe("ops", () => {
21
21
 
22
22
  test("ops.array creates an array", async () => {
23
23
  const code = createCode([ops.array, 1, 2, 3]);
24
- const result = await evaluate.call(null, code);
24
+ const result = await evaluate(code);
25
25
  assert.deepEqual(result, [1, 2, 3]);
26
26
  });
27
27
 
@@ -44,23 +44,22 @@ describe("ops", () => {
44
44
 
45
45
  test("ops.comma returns the last value", async () => {
46
46
  const code = createCode([ops.comma, 1, 2, 3]);
47
- const result = await evaluate.call(null, code);
47
+ const result = await evaluate(code);
48
48
  assert.strictEqual(result, 3);
49
49
  });
50
50
 
51
51
  test("ops.concat concatenates tree value text", async () => {
52
- const scope = new ObjectTree({
52
+ const container = {
53
53
  name: "world",
54
- });
55
-
54
+ };
56
55
  const code = createCode([
57
56
  ops.concat,
58
57
  "Hello, ",
59
- [[ops.scope], "name"],
58
+ [[ops.scope, container], "name"],
60
59
  ".",
61
60
  ]);
62
61
 
63
- const result = await evaluate.call(scope, code);
62
+ const result = await evaluate(code);
64
63
  assert.strictEqual(result, "Hello, world.");
65
64
  });
66
65
 
@@ -78,20 +77,6 @@ describe("ops", () => {
78
77
  assert.equal(await ops.construct(String, "hello"), "hello");
79
78
  });
80
79
 
81
- test("ops.context", async () => {
82
- const tree = new DeepObjectTree({
83
- a: {
84
- b: {
85
- c: {},
86
- },
87
- },
88
- });
89
- const b = await Tree.traverse(tree, "a", "b");
90
- const c = await b.get("c");
91
- assert.equal(ops.context.call(c), c);
92
- assert.equal(ops.context.call(c, 1), b);
93
- });
94
-
95
80
  test("ops.division divides two numbers", async () => {
96
81
  assert.strictEqual(ops.division(12, 2), 6);
97
82
  assert.strictEqual(ops.division(3, 2), 1.5);
@@ -114,23 +99,27 @@ describe("ops", () => {
114
99
 
115
100
  test("ops.cache evaluates code and cache its result", async () => {
116
101
  let count = 0;
117
- const tree = new DeepObjectTree({
102
+ const container = {
118
103
  group: {
119
104
  get count() {
120
105
  // Use promise to test async behavior
121
106
  return Promise.resolve(++count);
122
107
  },
123
108
  },
124
- });
109
+ };
125
110
  const code = createCode([
126
111
  ops.cache,
127
112
  {},
128
113
  "group/count",
129
- [[ops.scope], [ops.literal, "group"], [ops.literal, "count"]],
114
+ [
115
+ [ops.scope, container],
116
+ [ops.literal, "group"],
117
+ [ops.literal, "count"],
118
+ ],
130
119
  ]);
131
- const result = await evaluate.call(tree, code);
120
+ const result = await evaluate(code);
132
121
  assert.strictEqual(result, 1);
133
- const result2 = await evaluate.call(tree, code);
122
+ const result2 = await evaluate(code);
134
123
  assert.strictEqual(result2, 1);
135
124
  });
136
125
 
@@ -166,22 +155,36 @@ describe("ops", () => {
166
155
  assert(ops.greaterThanOrEqual("ab", "aa"));
167
156
  });
168
157
 
158
+ test("ops.inherited walks up the object parent chain", async () => {
159
+ const tree = new DeepObjectTree({
160
+ a: {
161
+ b: {},
162
+ },
163
+ });
164
+ const b = await Tree.traverse(tree, "a", "b");
165
+ assert.equal(await ops.inherited(2, { object: b }), tree);
166
+ });
167
+
169
168
  test("ops.lambda defines a function with no inputs", async () => {
170
169
  const code = createCode([ops.lambda, [], [ops.literal, "result"]]);
171
- const fn = await evaluate.call(null, code);
172
- const result = await fn.call();
170
+ const fn = await evaluate(code);
171
+ const result = await fn();
173
172
  assert.strictEqual(result, "result");
174
173
  });
175
174
 
176
175
  test("ops.lambda defines a function with underscore input", async () => {
177
- const scope = new ObjectTree({
176
+ const container = {
178
177
  message: "Hello",
179
- });
178
+ };
180
179
 
181
- const code = createCode([ops.lambda, ["_"], [[ops.scope], "message"]]);
180
+ const code = createCode([
181
+ ops.lambda,
182
+ ["_"],
183
+ [[ops.scope, container], "message"],
184
+ ]);
182
185
 
183
- const fn = await evaluate.call(scope, code);
184
- const result = await fn.call(scope);
186
+ const fn = await evaluate(code);
187
+ const result = await fn();
185
188
  assert.strictEqual(result, "Hello");
186
189
  });
187
190
 
@@ -192,9 +195,9 @@ describe("ops", () => {
192
195
  [ops.literal, "a"],
193
196
  [ops.literal, "b"],
194
197
  ],
195
- [ops.concat, [[ops.scope], "b"], [[ops.scope], "a"]],
198
+ [ops.concat, [[ops.params, 0], "b"], [[ops.params, 0], "a"]],
196
199
  ]);
197
- const fn = await evaluate.call(null, code);
200
+ const fn = await evaluate(code);
198
201
  const result = await fn("x", "y");
199
202
  assert.strictEqual(result, "yx");
200
203
  });
@@ -249,27 +252,27 @@ describe("ops", () => {
249
252
  // ...more
250
253
  // c: a
251
254
  // }
252
- const scope = new ObjectTree({
255
+ const container = {
253
256
  more: { b: 2 },
254
- });
257
+ };
255
258
  const code = createCode([
256
259
  [
257
260
  ops.object,
258
261
  ["a", [ops.literal, 1]],
259
- ["c", [[ops.context], "a"]],
262
+ ["c", [[ops.inherited, 0], "a"]],
260
263
  [
261
264
  "_result",
262
265
  [
263
266
  ops.merge,
264
- [ops.object, ["a", [ops.getter, [[ops.context, 1], "a"]]]],
265
- [[ops.scope], "more"],
266
- [ops.object, ["c", [ops.getter, [[ops.context, 1], "c"]]]],
267
+ [ops.object, ["a", [ops.getter, [[ops.inherited, 1], "a"]]]],
268
+ [[ops.scope, container], "more"],
269
+ [ops.object, ["c", [ops.getter, [[ops.inherited, 1], "c"]]]],
267
270
  ],
268
271
  ],
269
272
  ],
270
273
  "_result",
271
274
  ]);
272
- const result = await evaluate.call(scope, code);
275
+ const result = await evaluate(code);
273
276
  assert.deepEqual(await Tree.plain(result), { a: 1, b: 2, c: 1 });
274
277
  });
275
278
 
@@ -280,10 +283,10 @@ describe("ops", () => {
280
283
  assert.strictEqual(ops.multiplication("foo", 2), NaN);
281
284
  });
282
285
 
283
- test("ops.optionalTraverse", async () => {
284
- assert.equal(await ops.optionalTraverse(null, "a"), undefined);
285
- assert.equal(await ops.optionalTraverse({ a: 1 }, "a"), 1);
286
- });
286
+ // test("ops.optionalTraverse", async () => {
287
+ // assert.equal(await ops.optionalTraverse(null, "a"), undefined);
288
+ // assert.equal(await ops.optionalTraverse({ a: 1 }, "a"), 1);
289
+ // });
287
290
 
288
291
  test("ops.notEqual", () => {
289
292
  assert(!ops.notEqual(1, 1));
@@ -311,35 +314,44 @@ describe("ops", () => {
311
314
  });
312
315
 
313
316
  test("ops.object instantiates an object", async () => {
314
- const scope = new ObjectTree({
317
+ const container = {
315
318
  upper: (s) => s.toUpperCase(),
316
- });
319
+ };
317
320
 
318
321
  const code = createCode([
319
322
  ops.object,
320
- ["hello", [[[ops.scope], "upper"], "hello"]],
321
- ["world", [[[ops.scope], "upper"], "world"]],
323
+ ["hello", [[[ops.scope, container], "upper"], "hello"]],
324
+ ["world", [[[ops.scope, container], "upper"], "world"]],
322
325
  ]);
323
326
 
324
- const result = await evaluate.call(scope, code);
327
+ const result = await evaluate(code);
325
328
  assert.strictEqual(result.hello, "HELLO");
326
329
  assert.strictEqual(result.world, "WORLD");
327
330
  });
328
331
 
329
332
  test("ops.object instantiates an array", async () => {
330
- const scope = new ObjectTree({
333
+ const container = {
331
334
  upper: (s) => s.toUpperCase(),
332
- });
335
+ };
333
336
  const code = createCode([
334
337
  ops.array,
335
338
  "Hello",
336
339
  1,
337
- [[[ops.scope], "upper"], "world"],
340
+ [[[ops.scope, container], "upper"], "world"],
338
341
  ]);
339
- const result = await evaluate.call(scope, code);
342
+ const result = await evaluate(code);
340
343
  assert.deepEqual(result, ["Hello", 1, "WORLD"]);
341
344
  });
342
345
 
346
+ test("ops.params returns a stack frame", async () => {
347
+ const code = createCode([ops.params, 1]);
348
+ const frame1 = { a: 1 };
349
+ const frame2 = { b: 2 };
350
+ const stack = [frame1, frame2];
351
+ const result = await evaluate(code, { stack });
352
+ assert.strictEqual(result, frame1);
353
+ });
354
+
343
355
  test("ops.property returns a property if defined, otherwise traverses", async () => {
344
356
  assert.equal(await ops.property({ a: 1 }, "a"), 1);
345
357
  assert.equal(await ops.property({ a: 1 }, "b"), undefined);
@@ -355,30 +367,16 @@ describe("ops", () => {
355
367
  });
356
368
 
357
369
  describe("ops.scope", () => {
358
- test("returns the scope of the current tree", async () => {
359
- const tree = new DeepObjectTree({
360
- a: {
361
- b: {},
362
- },
363
- c: 1,
364
- });
365
- const a = await tree.get("a");
366
- const b = await a.get("b");
367
- const scope = await ops.scope.call(b);
368
- assert.equal(await scope?.get("c"), 1);
369
- });
370
-
371
- test("accepts an optional context", async () => {
370
+ test("returns the scope of the given tree", async () => {
372
371
  const tree = new DeepObjectTree({
373
372
  a: {
374
373
  b: {},
375
- c: 0, // shouldn't get this
376
374
  },
377
375
  c: 1,
378
376
  });
379
377
  const a = await tree.get("a");
380
378
  const b = await a.get("b");
381
- const scope = await ops.scope.call(b, tree);
379
+ const scope = await ops.scope(b);
382
380
  assert.equal(await scope?.get("c"), 1);
383
381
  });
384
382
  });
@@ -439,7 +437,7 @@ describe("ops", () => {
439
437
  test("ops.unpack unpacks a value", async () => {
440
438
  const fixture = new String("packed");
441
439
  /** @type {any} */ (fixture).unpack = async () => "unpacked";
442
- const result = await ops.unpack.call(null, fixture);
440
+ const result = await ops.unpack(fixture);
443
441
  assert.strictEqual(result, "unpacked");
444
442
  });
445
443
 
@@ -1,10 +0,0 @@
1
- import { Tree } from "@weborigami/async-tree";
2
-
3
- // Return the extension handlers for the given tree
4
- export default function getHandlers(tree) {
5
- if (!tree) {
6
- return null;
7
- }
8
- const root = Tree.root(tree);
9
- return /** @type {any} */ (root).handlers;
10
- }