@weborigami/language 0.3.3 → 0.3.4-jse.5
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/main.js +3 -1
- package/package.json +3 -3
- package/src/compiler/compile.js +13 -3
- package/src/compiler/isOrigamiFrontMatter.js +4 -3
- package/src/compiler/optimize.js +273 -106
- package/src/compiler/origami.pegjs +286 -169
- package/src/compiler/parse.js +2069 -1275
- package/src/compiler/parserHelpers.js +154 -145
- package/src/runtime/HandleExtensionsTransform.js +10 -1
- package/src/runtime/evaluate.js +28 -35
- package/src/runtime/expressionObject.js +17 -11
- package/src/runtime/getHandlers.js +10 -0
- package/src/runtime/handlers.js +18 -54
- package/src/runtime/jsGlobals.js +106 -0
- package/src/runtime/mergeTrees.js +0 -5
- package/src/runtime/ops.js +92 -161
- package/src/runtime/symbols.js +1 -0
- package/src/runtime/{taggedTemplateIndent.js → templateIndent.js} +2 -2
- package/test/compiler/codeHelpers.js +3 -1
- package/test/compiler/compile.test.js +60 -30
- package/test/compiler/optimize.test.js +263 -24
- package/test/compiler/parse.test.js +895 -521
- package/test/runtime/evaluate.test.js +4 -20
- package/test/runtime/expressionObject.test.js +6 -5
- package/test/runtime/handlers.test.js +19 -10
- package/test/runtime/mergeTrees.test.js +0 -5
- package/test/runtime/ops.test.js +103 -82
- package/test/runtime/taggedTemplateIndent.test.js +1 -1
|
@@ -8,7 +8,7 @@ import { createCode } from "../compiler/codeHelpers.js";
|
|
|
8
8
|
|
|
9
9
|
describe("evaluate", () => {
|
|
10
10
|
test("can retrieve values from scope", async () => {
|
|
11
|
-
const code = createCode([ops.scope, "message"]);
|
|
11
|
+
const code = createCode([[ops.scope], "message"]);
|
|
12
12
|
const parent = new ObjectTree({
|
|
13
13
|
message: "Hello",
|
|
14
14
|
});
|
|
@@ -21,8 +21,8 @@ describe("evaluate", () => {
|
|
|
21
21
|
test("can invoke functions in scope", async () => {
|
|
22
22
|
// Match the array representation of code generated by the parser.
|
|
23
23
|
const code = createCode([
|
|
24
|
-
[ops.scope, "greet"],
|
|
25
|
-
[ops.scope, "name"],
|
|
24
|
+
[[ops.scope], "greet"],
|
|
25
|
+
[[ops.scope], "name"],
|
|
26
26
|
]);
|
|
27
27
|
|
|
28
28
|
const tree = new ObjectTree({
|
|
@@ -37,7 +37,7 @@ describe("evaluate", () => {
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
test("passes context to invoked functions", async () => {
|
|
40
|
-
const code = createCode([ops.scope, "fn"]);
|
|
40
|
+
const code = createCode([[ops.scope], "fn"]);
|
|
41
41
|
const tree = new ObjectTree({
|
|
42
42
|
async fn() {
|
|
43
43
|
assert.equal(this, tree);
|
|
@@ -46,14 +46,6 @@ describe("evaluate", () => {
|
|
|
46
46
|
await evaluate.call(tree, code);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
test("evaluates a function with fixed number of arguments", async () => {
|
|
50
|
-
const fn = (x, y) => ({
|
|
51
|
-
c: `${x}${y}c`,
|
|
52
|
-
});
|
|
53
|
-
const code = createCode([ops.traverse, fn, "a", "b", "c"]);
|
|
54
|
-
assert.equal(await evaluate.call(null, code), "abc");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
49
|
test("if object in function position isn't a function, can unpack it", async () => {
|
|
58
50
|
const fn = (...args) => args.join(",");
|
|
59
51
|
const packed = new String();
|
|
@@ -62,12 +54,4 @@ describe("evaluate", () => {
|
|
|
62
54
|
const result = await evaluate.call(null, code);
|
|
63
55
|
assert.equal(result, "a,b,c");
|
|
64
56
|
});
|
|
65
|
-
|
|
66
|
-
test("by defalut sets the parent of a returned tree to the current tree", async () => {
|
|
67
|
-
const fn = () => new ObjectTree({});
|
|
68
|
-
const code = createCode([fn]);
|
|
69
|
-
const tree = new ObjectTree({});
|
|
70
|
-
const result = await evaluate.call(tree, code);
|
|
71
|
-
assert.equal(result.parent, tree);
|
|
72
|
-
});
|
|
73
57
|
});
|
|
@@ -12,8 +12,8 @@ describe("expressionObject", () => {
|
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
const entries = [
|
|
15
|
-
["hello", [[ops.scope, "upper"], "hello"]],
|
|
16
|
-
["world", [[ops.scope, "upper"], "world"]],
|
|
15
|
+
["hello", [[[ops.scope], "upper"], "hello"]],
|
|
16
|
+
["world", [[[ops.scope], "upper"], "world"]],
|
|
17
17
|
];
|
|
18
18
|
|
|
19
19
|
const object = await expressionObject(entries, scope);
|
|
@@ -40,7 +40,7 @@ describe("expressionObject", () => {
|
|
|
40
40
|
test("can instantiate an Origami tree", async () => {
|
|
41
41
|
const entries = [
|
|
42
42
|
["name", "world"],
|
|
43
|
-
["message", [ops.concat, "Hello, ", [ops.scope, "name"], "!"]],
|
|
43
|
+
["message", [ops.concat, "Hello, ", [[ops.scope], "name"], "!"]],
|
|
44
44
|
];
|
|
45
45
|
const parent = new ObjectTree({});
|
|
46
46
|
const object = await expressionObject(entries, parent);
|
|
@@ -53,11 +53,12 @@ describe("expressionObject", () => {
|
|
|
53
53
|
|
|
54
54
|
test("returned object values can be unpacked", async () => {
|
|
55
55
|
const entries = [["data.json", `{ "a": 1 }`]];
|
|
56
|
-
const parent = new ObjectTree({
|
|
56
|
+
const parent = new ObjectTree({});
|
|
57
|
+
parent.handlers = {
|
|
57
58
|
"json.handler": {
|
|
58
59
|
unpack: JSON.parse,
|
|
59
60
|
},
|
|
60
|
-
}
|
|
61
|
+
};
|
|
61
62
|
const result = await expressionObject(entries, parent);
|
|
62
63
|
const dataJson = await result["data.json"];
|
|
63
64
|
const json = await dataJson.unpack();
|
|
@@ -3,6 +3,12 @@ import assert from "node:assert";
|
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
import { handleExtension } from "../../src/runtime/handlers.js";
|
|
5
5
|
|
|
6
|
+
const handlers = {
|
|
7
|
+
"json.handler": {
|
|
8
|
+
unpack: (buffer) => JSON.parse(String(buffer)),
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
6
12
|
describe("handlers", () => {
|
|
7
13
|
test("attaches an unpack method to a value with an extension", async () => {
|
|
8
14
|
const fixture = createFixture();
|
|
@@ -10,7 +16,12 @@ describe("handlers", () => {
|
|
|
10
16
|
assert(typeof numberValue === "number");
|
|
11
17
|
assert.equal(numberValue, 1);
|
|
12
18
|
const jsonFile = await fixture.get("bar.json");
|
|
13
|
-
const withHandler = await handleExtension(
|
|
19
|
+
const withHandler = await handleExtension(
|
|
20
|
+
fixture,
|
|
21
|
+
jsonFile,
|
|
22
|
+
"bar.json",
|
|
23
|
+
handlers
|
|
24
|
+
);
|
|
14
25
|
assert.equal(String(withHandler), `{ "bar": 2 }`);
|
|
15
26
|
const data = await withHandler.unpack();
|
|
16
27
|
assert.deepEqual(data, { bar: 2 });
|
|
@@ -19,21 +30,19 @@ describe("handlers", () => {
|
|
|
19
30
|
test("immediately unpacks if key ends in slash", async () => {
|
|
20
31
|
const fixture = createFixture();
|
|
21
32
|
const jsonFile = await fixture.get("bar.json");
|
|
22
|
-
const data = await handleExtension(
|
|
33
|
+
const data = await handleExtension(
|
|
34
|
+
fixture,
|
|
35
|
+
jsonFile,
|
|
36
|
+
"bar.json/",
|
|
37
|
+
handlers
|
|
38
|
+
);
|
|
23
39
|
assert.deepEqual(data, { bar: 2 });
|
|
24
40
|
});
|
|
25
41
|
});
|
|
26
42
|
|
|
27
43
|
function createFixture() {
|
|
28
|
-
|
|
29
|
-
"json.handler": {
|
|
30
|
-
unpack: (buffer) => JSON.parse(String(buffer)),
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
let tree = new ObjectTree({
|
|
44
|
+
return new ObjectTree({
|
|
34
45
|
foo: 1, // No extension, should be left alone
|
|
35
46
|
"bar.json": `{ "bar": 2 }`,
|
|
36
47
|
});
|
|
37
|
-
tree.parent = parent;
|
|
38
|
-
return tree;
|
|
39
48
|
}
|
|
@@ -41,11 +41,6 @@ describe("mergeTrees", () => {
|
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
test("if all arguments are arrays, result is an array", async () => {
|
|
45
|
-
const result = await mergeTrees.call(null, [1, 2], [3, 4]);
|
|
46
|
-
assert.deepEqual(result, [1, 2, 3, 4]);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
44
|
test("merges heterogenous arguments as trees", async () => {
|
|
50
45
|
const tree = await mergeTrees.call(
|
|
51
46
|
null,
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeepObjectTree, ObjectTree } from "@weborigami/async-tree";
|
|
1
|
+
import { DeepObjectTree, ObjectTree, Tree } from "@weborigami/async-tree";
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
|
|
@@ -42,17 +42,6 @@ describe("ops", () => {
|
|
|
42
42
|
assert.strictEqual(ops.bitwiseXor(5, 3), 6);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
test("ops.builtin gets a value from the top of the scope chain", async () => {
|
|
46
|
-
const root = new ObjectTree({
|
|
47
|
-
a: 1,
|
|
48
|
-
});
|
|
49
|
-
const tree = new ObjectTree({});
|
|
50
|
-
tree.parent = root;
|
|
51
|
-
const code = createCode([ops.builtin, "a"]);
|
|
52
|
-
const result = await evaluate.call(tree, code);
|
|
53
|
-
assert.strictEqual(result, 1);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
45
|
test("ops.comma returns the last value", async () => {
|
|
57
46
|
const code = createCode([ops.comma, 1, 2, 3]);
|
|
58
47
|
const result = await evaluate.call(null, code);
|
|
@@ -64,7 +53,12 @@ describe("ops", () => {
|
|
|
64
53
|
name: "world",
|
|
65
54
|
});
|
|
66
55
|
|
|
67
|
-
const code = createCode([
|
|
56
|
+
const code = createCode([
|
|
57
|
+
ops.concat,
|
|
58
|
+
"Hello, ",
|
|
59
|
+
[[ops.scope], "name"],
|
|
60
|
+
".",
|
|
61
|
+
]);
|
|
68
62
|
|
|
69
63
|
const result = await evaluate.call(scope, code);
|
|
70
64
|
assert.strictEqual(result, "Hello, world.");
|
|
@@ -80,27 +74,22 @@ describe("ops", () => {
|
|
|
80
74
|
assert.strictEqual(await ops.conditional(false, errorFn, trueFn), true);
|
|
81
75
|
});
|
|
82
76
|
|
|
83
|
-
test("ops.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
test("ops.construct", async () => {
|
|
78
|
+
assert.equal(await ops.construct(String, "hello"), "hello");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("ops.context", async () => {
|
|
82
|
+
const tree = new DeepObjectTree({
|
|
83
|
+
a: {
|
|
84
|
+
b: {
|
|
85
|
+
c: {},
|
|
86
|
+
},
|
|
88
87
|
},
|
|
89
|
-
[
|
|
90
|
-
ops.lambda,
|
|
91
|
-
[["_"]],
|
|
92
|
-
[
|
|
93
|
-
ops.template,
|
|
94
|
-
[ops.literal, ["a = ", ""]],
|
|
95
|
-
[ops.concat, [ops.scope, "a"]],
|
|
96
|
-
],
|
|
97
|
-
],
|
|
98
|
-
]);
|
|
99
|
-
const result = await evaluate.call(null, code);
|
|
100
|
-
assert.deepEqual(result, {
|
|
101
|
-
a: 1,
|
|
102
|
-
"@text": "a = 1",
|
|
103
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);
|
|
104
93
|
});
|
|
105
94
|
|
|
106
95
|
test("ops.division divides two numbers", async () => {
|
|
@@ -123,20 +112,21 @@ describe("ops", () => {
|
|
|
123
112
|
assert.strictEqual(ops.exponentiation(2, 0), 1);
|
|
124
113
|
});
|
|
125
114
|
|
|
126
|
-
test("ops.
|
|
115
|
+
test("ops.cache evaluates code and cache its result", async () => {
|
|
127
116
|
let count = 0;
|
|
128
117
|
const tree = new DeepObjectTree({
|
|
129
118
|
group: {
|
|
130
119
|
get count() {
|
|
131
|
-
|
|
120
|
+
// Use promise to test async behavior
|
|
121
|
+
return Promise.resolve(++count);
|
|
132
122
|
},
|
|
133
123
|
},
|
|
134
124
|
});
|
|
135
125
|
const code = createCode([
|
|
136
|
-
ops.
|
|
137
|
-
"group/count",
|
|
138
|
-
[ops.traverse, [ops.scope, "group"], [ops.literal, "count"]],
|
|
126
|
+
ops.cache,
|
|
139
127
|
{},
|
|
128
|
+
"group/count",
|
|
129
|
+
[[ops.scope], [ops.literal, "group"], [ops.literal, "count"]],
|
|
140
130
|
]);
|
|
141
131
|
const result = await evaluate.call(tree, code);
|
|
142
132
|
assert.strictEqual(result, 1);
|
|
@@ -144,6 +134,26 @@ describe("ops", () => {
|
|
|
144
134
|
assert.strictEqual(result2, 1);
|
|
145
135
|
});
|
|
146
136
|
|
|
137
|
+
describe("ops.flat", () => {
|
|
138
|
+
test("flattens arrays", async () => {
|
|
139
|
+
assert.deepEqual(await ops.flat(1, 2, [3]), [1, 2, 3]);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("flattens treelike objects", async () => {
|
|
143
|
+
const object = {
|
|
144
|
+
a: 1,
|
|
145
|
+
b: 2,
|
|
146
|
+
};
|
|
147
|
+
const tree = new ObjectTree({
|
|
148
|
+
c: 3,
|
|
149
|
+
d: 4,
|
|
150
|
+
});
|
|
151
|
+
const array = [5, 6];
|
|
152
|
+
const result = await ops.flat(object, tree, array);
|
|
153
|
+
assert.deepEqual(result, [1, 2, 3, 4, 5, 6]);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
147
157
|
test("ops.greaterThan", () => {
|
|
148
158
|
assert(ops.greaterThan(5, 3));
|
|
149
159
|
assert(!ops.greaterThan(3, 3));
|
|
@@ -156,20 +166,6 @@ describe("ops", () => {
|
|
|
156
166
|
assert(ops.greaterThanOrEqual("ab", "aa"));
|
|
157
167
|
});
|
|
158
168
|
|
|
159
|
-
test("ops.inherited searches inherited scope", async () => {
|
|
160
|
-
const parent = new ObjectTree({
|
|
161
|
-
a: 1, // This is the inherited value we want
|
|
162
|
-
});
|
|
163
|
-
/** @type {any} */
|
|
164
|
-
const child = new ObjectTree({
|
|
165
|
-
a: 2, // Should be ignored
|
|
166
|
-
});
|
|
167
|
-
child.parent = parent;
|
|
168
|
-
const code = createCode([ops.inherited, "a"]);
|
|
169
|
-
const result = await evaluate.call(child, code);
|
|
170
|
-
assert.strictEqual(result, 1);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
169
|
test("ops.lambda defines a function with no inputs", async () => {
|
|
174
170
|
const code = createCode([ops.lambda, [], [ops.literal, "result"]]);
|
|
175
171
|
const fn = await evaluate.call(null, code);
|
|
@@ -182,7 +178,7 @@ describe("ops", () => {
|
|
|
182
178
|
message: "Hello",
|
|
183
179
|
});
|
|
184
180
|
|
|
185
|
-
const code = createCode([ops.lambda, ["_"], [ops.scope, "message"]]);
|
|
181
|
+
const code = createCode([ops.lambda, ["_"], [[ops.scope], "message"]]);
|
|
186
182
|
|
|
187
183
|
const fn = await evaluate.call(scope, code);
|
|
188
184
|
const result = await fn.call(scope);
|
|
@@ -196,7 +192,7 @@ describe("ops", () => {
|
|
|
196
192
|
[ops.literal, "a"],
|
|
197
193
|
[ops.literal, "b"],
|
|
198
194
|
],
|
|
199
|
-
[ops.concat, [ops.scope, "b"], [ops.scope, "a"]],
|
|
195
|
+
[ops.concat, [[ops.scope], "b"], [[ops.scope], "a"]],
|
|
200
196
|
]);
|
|
201
197
|
const fn = await evaluate.call(null, code);
|
|
202
198
|
const result = await fn("x", "y");
|
|
@@ -250,40 +246,31 @@ describe("ops", () => {
|
|
|
250
246
|
test("ops.merge", async () => {
|
|
251
247
|
// {
|
|
252
248
|
// a: 1
|
|
253
|
-
// …
|
|
254
|
-
// }
|
|
255
|
-
const scope = new ObjectTree({
|
|
256
|
-
fn: (a) => ({ b: 2 * a }),
|
|
257
|
-
});
|
|
258
|
-
const code = createCode([
|
|
259
|
-
ops.merge,
|
|
260
|
-
[ops.object, ["a", [ops.literal, 1]]],
|
|
261
|
-
[
|
|
262
|
-
[ops.builtin, "fn"],
|
|
263
|
-
[ops.scope, "a"],
|
|
264
|
-
],
|
|
265
|
-
]);
|
|
266
|
-
const result = await evaluate.call(scope, code);
|
|
267
|
-
assert.deepEqual(result, { a: 1, b: 2 });
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
test("ops.merge lets all direct properties see each other", async () => {
|
|
271
|
-
// {
|
|
272
|
-
// a: 1
|
|
273
|
-
// ...more
|
|
249
|
+
// …more
|
|
274
250
|
// c: a
|
|
275
251
|
// }
|
|
276
252
|
const scope = new ObjectTree({
|
|
277
253
|
more: { b: 2 },
|
|
278
254
|
});
|
|
279
255
|
const code = createCode([
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
256
|
+
[
|
|
257
|
+
ops.object,
|
|
258
|
+
["a", [ops.literal, 1]],
|
|
259
|
+
["c", [[ops.context], "a"]],
|
|
260
|
+
[
|
|
261
|
+
"_result",
|
|
262
|
+
[
|
|
263
|
+
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
|
+
],
|
|
268
|
+
],
|
|
269
|
+
],
|
|
270
|
+
"_result",
|
|
284
271
|
]);
|
|
285
272
|
const result = await evaluate.call(scope, code);
|
|
286
|
-
assert.deepEqual(result, { a: 1, b: 2, c: 1 });
|
|
273
|
+
assert.deepEqual(await Tree.plain(result), { a: 1, b: 2, c: 1 });
|
|
287
274
|
});
|
|
288
275
|
|
|
289
276
|
test("ops.multiplication multiplies two numbers", async () => {
|
|
@@ -293,6 +280,11 @@ describe("ops", () => {
|
|
|
293
280
|
assert.strictEqual(ops.multiplication("foo", 2), NaN);
|
|
294
281
|
});
|
|
295
282
|
|
|
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
|
+
});
|
|
287
|
+
|
|
296
288
|
test("ops.notEqual", () => {
|
|
297
289
|
assert(!ops.notEqual(1, 1));
|
|
298
290
|
assert(ops.notEqual(1, 2));
|
|
@@ -325,8 +317,8 @@ describe("ops", () => {
|
|
|
325
317
|
|
|
326
318
|
const code = createCode([
|
|
327
319
|
ops.object,
|
|
328
|
-
["hello", [[ops.scope, "upper"], "hello"]],
|
|
329
|
-
["world", [[ops.scope, "upper"], "world"]],
|
|
320
|
+
["hello", [[[ops.scope], "upper"], "hello"]],
|
|
321
|
+
["world", [[[ops.scope], "upper"], "world"]],
|
|
330
322
|
]);
|
|
331
323
|
|
|
332
324
|
const result = await evaluate.call(scope, code);
|
|
@@ -342,7 +334,7 @@ describe("ops", () => {
|
|
|
342
334
|
ops.array,
|
|
343
335
|
"Hello",
|
|
344
336
|
1,
|
|
345
|
-
[[ops.scope, "upper"], "world"],
|
|
337
|
+
[[[ops.scope], "upper"], "world"],
|
|
346
338
|
]);
|
|
347
339
|
const result = await evaluate.call(scope, code);
|
|
348
340
|
assert.deepEqual(result, ["Hello", 1, "WORLD"]);
|
|
@@ -355,6 +347,35 @@ describe("ops", () => {
|
|
|
355
347
|
assert.strictEqual(ops.remainder(-4, 2), -0);
|
|
356
348
|
});
|
|
357
349
|
|
|
350
|
+
describe("ops.scope", () => {
|
|
351
|
+
test("returns the scope of the current tree", async () => {
|
|
352
|
+
const tree = new DeepObjectTree({
|
|
353
|
+
a: {
|
|
354
|
+
b: {},
|
|
355
|
+
},
|
|
356
|
+
c: 1,
|
|
357
|
+
});
|
|
358
|
+
const a = await tree.get("a");
|
|
359
|
+
const b = await a.get("b");
|
|
360
|
+
const scope = await ops.scope.call(b);
|
|
361
|
+
assert.equal(await scope.get("c"), 1);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test("accepts an optional context", async () => {
|
|
365
|
+
const tree = new DeepObjectTree({
|
|
366
|
+
a: {
|
|
367
|
+
b: {},
|
|
368
|
+
c: 0, // shouldn't get this
|
|
369
|
+
},
|
|
370
|
+
c: 1,
|
|
371
|
+
});
|
|
372
|
+
const a = await tree.get("a");
|
|
373
|
+
const b = await a.get("b");
|
|
374
|
+
const scope = await ops.scope.call(b, tree);
|
|
375
|
+
assert.equal(await scope.get("c"), 1);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
358
379
|
test("ops.shiftLeft", () => {
|
|
359
380
|
assert.strictEqual(ops.shiftLeft(5, 2), 20);
|
|
360
381
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
|
-
import indent from "../../src/runtime/
|
|
3
|
+
import indent from "../../src/runtime/templateIndent.js";
|
|
4
4
|
|
|
5
5
|
describe("taggedTemplateIndent", () => {
|
|
6
6
|
test("joins strings and values together if template isn't a block template", async () => {
|