@weborigami/language 0.7.0-beta.1 → 0.7.0-beta.3

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 (43) hide show
  1. package/main.js +1 -0
  2. package/package.json +3 -2
  3. package/src/compiler/compile.js +0 -3
  4. package/src/compiler/optimize.js +56 -23
  5. package/src/compiler/parserHelpers.js +11 -8
  6. package/src/handlers/addExtensionKeyFn.js +18 -0
  7. package/src/handlers/epub_handler.js +54 -0
  8. package/src/handlers/getSource.js +1 -0
  9. package/src/handlers/handlers.js +2 -0
  10. package/src/handlers/ori_handler.js +2 -2
  11. package/src/handlers/oridocument_handler.js +5 -21
  12. package/src/handlers/{processOriExport.js → processOrigamiExport.js} +1 -1
  13. package/src/handlers/zip_handler.js +112 -0
  14. package/src/runtime/AsyncCacheTransform.d.ts +5 -1
  15. package/src/runtime/AsyncCacheTransform.js +22 -25
  16. package/src/runtime/OrigamiFileMap.js +3 -3
  17. package/src/runtime/SyncCacheTransform.d.ts +2 -1
  18. package/src/runtime/SyncCacheTransform.js +31 -34
  19. package/src/runtime/SystemCacheMap.js +28 -17
  20. package/src/runtime/counters.js +3 -0
  21. package/src/runtime/enableValueCaching.js +8 -7
  22. package/src/runtime/errors.js +33 -1
  23. package/src/runtime/execute.js +3 -0
  24. package/src/runtime/explainReferenceError.js +11 -24
  25. package/src/runtime/explainTraverseError.js +15 -6
  26. package/src/runtime/expressionObject.js +53 -34
  27. package/src/runtime/handleExtension.js +18 -9
  28. package/src/runtime/ops.js +4 -3
  29. package/test/compiler/compile.test.js +0 -1
  30. package/test/compiler/optimize.test.js +60 -15
  31. package/test/compiler/parse.test.js +38 -9
  32. package/test/handlers/epub_handler.test.js +27 -0
  33. package/test/handlers/fixtures/test.zip +0 -0
  34. package/test/handlers/zip_handler.test.js +45 -0
  35. package/test/runtime/AsyncCacheTransform.test.js +9 -4
  36. package/test/runtime/SyncCacheTransform.test.js +4 -0
  37. package/test/runtime/asyncCalcs.js +26 -4
  38. package/test/runtime/errors.test.js +4 -4
  39. package/test/runtime/expressionObject.test.js +23 -12
  40. package/test/runtime/handleExtension.test.js +0 -2
  41. package/test/runtime/ops.test.js +5 -3
  42. package/test/runtime/syncCalcs.js +26 -3
  43. package/test/runtime/systemCache.test.js +4 -0
@@ -23,7 +23,7 @@ describe("expressionObject", () => {
23
23
  ];
24
24
  const context = new SyncMap();
25
25
 
26
- const object = await expressionObject(entries, {
26
+ const object = await expressionObject("test.ori/", entries, {
27
27
  object: context,
28
28
  parent,
29
29
  });
@@ -36,7 +36,7 @@ describe("expressionObject", () => {
36
36
  let count = 0;
37
37
  const increment = () => count++;
38
38
  const entries = [["count", [increment]]];
39
- const object = await expressionObject(entries);
39
+ const object = await expressionObject("test.ori/", entries);
40
40
  const propertyDescriptor = Object.getOwnPropertyDescriptor(object, "count");
41
41
  assert.equal(propertyDescriptor?.value, 0);
42
42
  assert.equal(object.count, 0);
@@ -47,7 +47,7 @@ describe("expressionObject", () => {
47
47
  let count = 0;
48
48
  const increment = () => count++;
49
49
  const entries = [["count", [ops.getter, [increment]]]];
50
- const object = await expressionObject(entries);
50
+ const object = await expressionObject("test.ori/", entries);
51
51
  object[cachePathSymbol] = "foo.ori/"; // enable caching on this object tree
52
52
  assert.equal(await object.count, 0);
53
53
  const propertyDescriptor = Object.getOwnPropertyDescriptor(object, "count");
@@ -58,7 +58,7 @@ describe("expressionObject", () => {
58
58
 
59
59
  test("treats a getter for a primitive value as a regular property", async () => {
60
60
  const entries = [["name", [ops.getter, "world"]]];
61
- const object = await expressionObject(entries);
61
+ const object = await expressionObject("test.ori/", entries);
62
62
  assert.equal(object.name, "world");
63
63
  });
64
64
 
@@ -68,7 +68,9 @@ describe("expressionObject", () => {
68
68
  ["message", [ops.deepText, "Hello, ", [[ops.inherited, 0], "name"], "!"]],
69
69
  ];
70
70
  const context = new SyncMap();
71
- const object = await expressionObject(entries, { object: context });
71
+ const object = await expressionObject("test.ori/", entries, {
72
+ object: context,
73
+ });
72
74
  assert.deepEqual(await Tree.plain(object), {
73
75
  name: "world",
74
76
  message: "Hello, world!",
@@ -92,7 +94,9 @@ describe("expressionObject", () => {
92
94
  ["name", "data"],
93
95
  ];
94
96
  const context = new SyncMap();
95
- const object = await expressionObject(entries, { object: context });
97
+ const object = await expressionObject("test.ori/", entries, {
98
+ object: context,
99
+ });
96
100
  assert.deepEqual(await Tree.plain(object), {
97
101
  "data.json": 1,
98
102
  name: "data",
@@ -105,7 +109,7 @@ describe("expressionObject", () => {
105
109
  const globals = {
106
110
  json_handler: { unpack: (data) => JSON.parse(data) },
107
111
  };
108
- const result = await expressionObject(entries, {
112
+ const result = await expressionObject("test.ori/", entries, {
109
113
  object: context,
110
114
  globals,
111
115
  });
@@ -119,7 +123,7 @@ describe("expressionObject", () => {
119
123
  ["(hidden)", "shh"],
120
124
  ["visible", "hey"],
121
125
  ];
122
- const object = await expressionObject(entries);
126
+ const object = await expressionObject("test.ori/", entries);
123
127
  assert.deepEqual(Object.keys(object), ["visible"]);
124
128
  assert.equal(object["hidden"], "shh");
125
129
  });
@@ -127,15 +131,15 @@ describe("expressionObject", () => {
127
131
  test("provides a symbols.keys method returning normalized keys", async () => {
128
132
  const entries = [
129
133
  // Will return a tree, should have a slash
130
- ["getter", [ops.getter, [ops.object, ["b", [ops.literal, 2]]]]],
134
+ ["getter", [ops.getter, [ops.object, null, ["b", [ops.literal, 2]]]]],
131
135
  ["hasSlash/", "This isn't really a tree but says it is"],
132
136
  ["message", "Hello"],
133
137
  // Immediate maplike value, should have a slash
134
- ["object", [ops.object, ["b", [ops.literal, 2]]]],
138
+ ["object", [ops.object, null, ["b", [ops.literal, 2]]]],
135
139
  // Computed key
136
140
  [[ops.deepText, [ops.array, "data", ".json"]], 1],
137
141
  ];
138
- const object = await expressionObject(entries);
142
+ const object = await expressionObject("test.ori/", entries);
139
143
  assert.deepEqual(object[symbols.keys](), [
140
144
  "getter/",
141
145
  "hasSlash/",
@@ -152,7 +156,7 @@ describe("expressionObject", () => {
152
156
  const getNumber = () =>
153
157
  systemCache.getOrInsertComputed("dependency", () => 1);
154
158
  const entries = [["number", [ops.getter, [getNumber]]]];
155
- const object = await expressionObject(entries);
159
+ const object = await expressionObject("test.ori/", entries);
156
160
  object[cachePathSymbol] = "src/test.ori/"; // enable caching on this object tree
157
161
  const number = await object.number;
158
162
  assert.equal(number, 1);
@@ -162,4 +166,11 @@ describe("expressionObject", () => {
162
166
  assert(dependencyEntry.downstreams.has("src/test.ori/number"));
163
167
  assert(objectEntry.upstreams.has("dependency"));
164
168
  });
169
+
170
+ test("generates a unique cache path for an unattached object", async () => {
171
+ const object0 = await expressionObject("test.ori/_objects/", [["a", 1]]);
172
+ assert.equal(object0[cachePathSymbol], "test.ori/_objects/0/");
173
+ const object1 = await expressionObject("test.ori/_objects/", [["a", 1]]);
174
+ assert.equal(object1[cachePathSymbol], "test.ori/_objects/1/");
175
+ });
165
176
  });
@@ -4,11 +4,9 @@ import { describe, test } from "node:test";
4
4
  import * as handlers from "../../src/handlers/handlers.js";
5
5
  import handleExtension from "../../src/runtime/handleExtension.js";
6
6
  import OrigamiFileMap from "../../src/runtime/OrigamiFileMap.js";
7
- import { cachePathSymbol } from "../../src/runtime/symbols.js";
8
7
 
9
8
  const fixturesUrl = new URL("fixtures/unpack", import.meta.url);
10
9
  const fixtureFiles = new OrigamiFileMap(fixturesUrl);
11
- fixtureFiles[cachePathSymbol] = "fixtures";
12
10
  fixtureFiles.globals = handlers;
13
11
 
14
12
  describe("handleExtension", () => {
@@ -56,7 +56,7 @@ describe("ops", () => {
56
56
 
57
57
  test("ops.cache", async () => {
58
58
  const fn = () => 1;
59
- const code = createCode([ops.object, ["a", [ops.getter, [fn]]]]);
59
+ const code = createCode([ops.object, null, ["a", [ops.getter, [fn]]]]);
60
60
  const result = await ops.cache("a.ori/_refs/b.ori/", code, {});
61
61
  assert.deepEqual(await Tree.plain(result), { a: 1 });
62
62
  const cachedResult = await systemCache.get("a.ori/_refs/b.ori/");
@@ -333,15 +333,16 @@ describe("ops", () => {
333
333
  const code = createCode([
334
334
  [
335
335
  ops.object,
336
+ null,
336
337
  ["a", [ops.literal, 1]],
337
338
  ["c", [[ops.inherited, 0], "a"]],
338
339
  [
339
340
  "_result",
340
341
  [
341
342
  ops.merge,
342
- [ops.object, ["a", [ops.getter, [[ops.inherited, 1], "a"]]]],
343
+ [ops.object, null, ["a", [ops.getter, [[ops.inherited, 1], "a"]]]],
343
344
  [[ops.scope], "more"],
344
- [ops.object, ["c", [ops.getter, [[ops.inherited, 1], "c"]]]],
345
+ [ops.object, null, ["c", [ops.getter, [[ops.inherited, 1], "c"]]]],
345
346
  ],
346
347
  ],
347
348
  ],
@@ -390,6 +391,7 @@ describe("ops", () => {
390
391
 
391
392
  const code = createCode([
392
393
  ops.object,
394
+ null,
393
395
  ["hello", [[[ops.scope], "upper"], "hello"]],
394
396
  ["world", [[[ops.scope], "upper"], "world"]],
395
397
  ]);
@@ -2,12 +2,35 @@ import { SyncMap } from "@weborigami/async-tree";
2
2
  import SyncCacheTransform from "../../src/runtime/SyncCacheTransform.js";
3
3
 
4
4
  export default function syncCalcs(iterable) {
5
- const data = new (SyncCacheTransform(SyncMap))(iterable);
6
- const calcs = new (SyncCacheTransform(SyncResultsMap))(data);
5
+ const data = new (SyncCacheTransform(SyncDataMap))(new Map(iterable));
6
+ const calcs = new (SyncCacheTransform(SyncCalcsMap))(data);
7
7
  return { calcs, data };
8
8
  }
9
9
 
10
- class SyncResultsMap extends SyncMap {
10
+ class SyncDataMap extends SyncMap {
11
+ constructor(source) {
12
+ super();
13
+ this.source = source;
14
+ }
15
+
16
+ delete(key) {
17
+ return this.source.delete(key);
18
+ }
19
+
20
+ get(key) {
21
+ return this.source.get(key);
22
+ }
23
+
24
+ keys() {
25
+ return this.source.keys();
26
+ }
27
+
28
+ set(key, value) {
29
+ return this.source.set(key, value);
30
+ }
31
+ }
32
+
33
+ class SyncCalcsMap extends SyncMap {
11
34
  constructor(source) {
12
35
  super();
13
36
  this.source = source;
@@ -48,12 +48,16 @@ describe("systemCache", () => {
48
48
 
49
49
  // Add new data.json to src folder, overriding the one in project root
50
50
  src.set("data.json", "2");
51
+ // Manually trigger cache invalidation
52
+ src.onValueChange("data.json");
51
53
 
52
54
  const value2 = await site.value;
53
55
  assert.equal(value2, 2);
54
56
 
55
57
  // Delete data.json from src folder, reverting to the one in project root
56
58
  src.delete("data.json");
59
+ // Manually trigger cache invalidation
60
+ src.onValueChange("data.json");
57
61
 
58
62
  const value3 = await site.value;
59
63
  assert.equal(value3, 1);