@weborigami/language 0.6.12 → 0.6.14
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.
|
|
3
|
+
"version": "0.6.14",
|
|
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.
|
|
14
|
+
"@weborigami/async-tree": "0.6.14",
|
|
15
15
|
"exif-parser": "0.1.12",
|
|
16
16
|
"watcher": "2.3.1",
|
|
17
17
|
"yaml": "2.8.2"
|
|
@@ -316,21 +316,21 @@ export function makeLambda(params, body, location) {
|
|
|
316
316
|
*
|
|
317
317
|
* {
|
|
318
318
|
* x = { a: 1 }
|
|
319
|
-
* ...
|
|
320
|
-
*
|
|
319
|
+
* ...y
|
|
320
|
+
* z = { b: 2}
|
|
321
321
|
* }
|
|
322
322
|
*
|
|
323
323
|
* will be treated as:
|
|
324
324
|
*
|
|
325
325
|
* {
|
|
326
326
|
* x = { a: 1 }
|
|
327
|
-
*
|
|
328
|
-
* _result:
|
|
329
|
-
* x
|
|
330
|
-
* ...x
|
|
327
|
+
* z = { b: 2}
|
|
328
|
+
* _result: ops.merge(
|
|
329
|
+
* { x }
|
|
331
330
|
* y
|
|
332
|
-
*
|
|
333
|
-
*
|
|
331
|
+
* { z }
|
|
332
|
+
* )
|
|
333
|
+
* }._result
|
|
334
334
|
*
|
|
335
335
|
* @param {*} spreads
|
|
336
336
|
* @param {CodeLocation} location
|
|
@@ -338,6 +338,7 @@ export function makeLambda(params, body, location) {
|
|
|
338
338
|
function makeMerge(spreads, location) {
|
|
339
339
|
const topEntries = [];
|
|
340
340
|
const resultEntries = [];
|
|
341
|
+
|
|
341
342
|
for (const spread of spreads) {
|
|
342
343
|
if (spread[0] === ops.object) {
|
|
343
344
|
topEntries.push(...spread.slice(1));
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isPlainObject,
|
|
3
|
+
isUnpackable,
|
|
4
|
+
symbols,
|
|
5
|
+
trailingSlash,
|
|
6
|
+
Tree,
|
|
7
|
+
} from "@weborigami/async-tree";
|
|
2
8
|
import assignPropertyDescriptors from "./assignPropertyDescriptors.js";
|
|
3
9
|
|
|
4
10
|
/**
|
|
@@ -28,11 +34,48 @@ export default async function mergeTrees(...trees) {
|
|
|
28
34
|
|
|
29
35
|
// If all trees are plain objects, return a plain object.
|
|
30
36
|
if (unpacked.every((tree) => isPlainObject(tree) && !Tree.isMap(tree))) {
|
|
31
|
-
|
|
32
|
-
return assignPropertyDescriptors({}, ...unpacked);
|
|
37
|
+
return mergePlainObjects(...unpacked);
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
// Merge the trees.
|
|
36
41
|
const result = Tree.merge(...unpacked);
|
|
37
42
|
return result;
|
|
38
43
|
}
|
|
44
|
+
|
|
45
|
+
// Return the merged keys for the given objects, respecting any keys method on
|
|
46
|
+
// objects that were created using Origami object literals. This preserves
|
|
47
|
+
// trailing slashes.
|
|
48
|
+
function mergeObjectKeys(objects) {
|
|
49
|
+
const mergedKeys = new Set();
|
|
50
|
+
for (const obj of objects) {
|
|
51
|
+
const objectKeys =
|
|
52
|
+
typeof obj[symbols.keys] === "function"
|
|
53
|
+
? obj[symbols.keys]()
|
|
54
|
+
: Object.keys(obj);
|
|
55
|
+
for (const key of objectKeys) {
|
|
56
|
+
const alternateKey = trailingSlash.toggle(key);
|
|
57
|
+
if (mergedKeys.has(alternateKey)) {
|
|
58
|
+
// The new key differs from a key from an earlier object key only by the
|
|
59
|
+
// presence or absence of a trailing slash. Replace that old key.
|
|
60
|
+
mergedKeys.delete(alternateKey);
|
|
61
|
+
}
|
|
62
|
+
mergedKeys.add(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Array.from(mergedKeys);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function mergePlainObjects(...objects) {
|
|
69
|
+
// Use our Object.assign variation that avoids invoking property getters.
|
|
70
|
+
const result = assignPropertyDescriptors({}, ...objects);
|
|
71
|
+
|
|
72
|
+
// Attach a keys method
|
|
73
|
+
Object.defineProperty(result, symbols.keys, {
|
|
74
|
+
configurable: true,
|
|
75
|
+
enumerable: false,
|
|
76
|
+
value: () => mergeObjectKeys(objects),
|
|
77
|
+
writable: true,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return result;
|
|
81
|
+
}
|
package/src/runtime/ops.js
CHANGED
|
@@ -173,23 +173,12 @@ export function exponentiation(a, b) {
|
|
|
173
173
|
addOpLabel(exponentiation, "«ops.exponentiation»");
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
* Flatten the values of the given trees
|
|
176
|
+
* Flatten the values of the given trees by one level.
|
|
177
177
|
*
|
|
178
178
|
* @param {...any} args
|
|
179
179
|
*/
|
|
180
180
|
export async function flat(...args) {
|
|
181
|
-
|
|
182
|
-
args.map(async (arg) => {
|
|
183
|
-
if (isUnpackable(arg)) {
|
|
184
|
-
arg = await arg.unpack();
|
|
185
|
-
}
|
|
186
|
-
return arg instanceof Array || typeof arg !== "object"
|
|
187
|
-
? arg
|
|
188
|
-
: await Tree.values(arg);
|
|
189
|
-
}),
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
return arrays.flat();
|
|
181
|
+
return Tree.flat(args);
|
|
193
182
|
}
|
|
194
183
|
addOpLabel(flat, "«ops.flat»");
|
|
195
184
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ObjectMap, Tree } from "@weborigami/async-tree";
|
|
1
|
+
import { ObjectMap, symbols, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
import mergeTrees from "../../src/runtime/mergeTrees.js";
|
|
@@ -23,7 +23,7 @@ describe("mergeTrees", () => {
|
|
|
23
23
|
calledBar = true;
|
|
24
24
|
return true;
|
|
25
25
|
},
|
|
26
|
-
}
|
|
26
|
+
},
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
// Shouldn't call functions when just getting keys
|
|
@@ -40,6 +40,22 @@ describe("mergeTrees", () => {
|
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
test("respects trailing slashes in keys", async () => {
|
|
44
|
+
const result = await mergeTrees(
|
|
45
|
+
{
|
|
46
|
+
"a/": 1, // key will be overwritten
|
|
47
|
+
b: 2, // key will be overwritten
|
|
48
|
+
c: 3,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
a: 4,
|
|
52
|
+
"b/": 5,
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
const keys = result[symbols.keys]();
|
|
56
|
+
assert.deepEqual(keys, ["c", "a", "b/"]);
|
|
57
|
+
});
|
|
58
|
+
|
|
43
59
|
test("merges heterogenous arguments as trees", async () => {
|
|
44
60
|
const tree = await mergeTrees(
|
|
45
61
|
new ObjectMap({
|
|
@@ -49,7 +65,7 @@ describe("mergeTrees", () => {
|
|
|
49
65
|
{
|
|
50
66
|
b: 3,
|
|
51
67
|
c: 4,
|
|
52
|
-
}
|
|
68
|
+
},
|
|
53
69
|
);
|
|
54
70
|
assert.deepEqual(await Tree.plain(tree), {
|
|
55
71
|
a: 1,
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -159,7 +159,14 @@ describe("ops", () => {
|
|
|
159
159
|
});
|
|
160
160
|
const array = [5, 6];
|
|
161
161
|
const result = await ops.flat(object, tree, array);
|
|
162
|
-
assert.deepEqual(result,
|
|
162
|
+
assert.deepEqual(await Tree.plain(result), {
|
|
163
|
+
a: 1,
|
|
164
|
+
b: 2,
|
|
165
|
+
c: 3,
|
|
166
|
+
d: 4,
|
|
167
|
+
0: 5,
|
|
168
|
+
1: 6,
|
|
169
|
+
});
|
|
163
170
|
});
|
|
164
171
|
});
|
|
165
172
|
|