@weborigami/language 0.0.61 → 0.0.62

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.
@@ -1,5 +1,4 @@
1
- import { isStringLike } from "@weborigami/async-tree";
2
- import handleExtension from "./handleExtension.js";
1
+ import { attachHandlerIfApplicable } from "./extensions.js";
3
2
 
4
3
  /**
5
4
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
@@ -12,13 +11,7 @@ export default function HandleExtensionsTransform(Base) {
12
11
  return class FileLoaders extends Base {
13
12
  async get(key) {
14
13
  let value = await super.get(key);
15
-
16
- // If the key is string-like and has an extension, attach a loader (if one
17
- // exists) that handles that extension.
18
- if (value && isStringLike(key)) {
19
- value = await handleExtension(this, String(key), value);
20
- }
21
-
14
+ value = attachHandlerIfApplicable(this, value, key);
22
15
  return value;
23
16
  }
24
17
  };
@@ -1,10 +1,10 @@
1
1
  import { FileTree } from "@weborigami/async-tree";
2
2
  import EventTargetMixin from "./EventTargetMixin.js";
3
+ import HandleExtensionsTransform from "./HandleExtensionsTransform.js";
3
4
  import ImportModulesMixin from "./ImportModulesMixin.js";
4
- import OrigamiTransform from "./OrigamiTransform.js";
5
5
  import WatchFilesMixin from "./WatchFilesMixin.js";
6
6
 
7
- export default class OrigamiFiles extends OrigamiTransform(
7
+ export default class OrigamiFiles extends HandleExtensionsTransform(
8
8
  (
9
9
  ImportModulesMixin(WatchFilesMixin(EventTargetMixin(FileTree)))
10
10
  )
@@ -1,9 +1,9 @@
1
1
  import { FileTree } from "@weborigami/async-tree";
2
2
  import EventTargetMixin from "./EventTargetMixin.js";
3
+ import HandleExtensionsTransform from "./HandleExtensionsTransform.js";
3
4
  import ImportModulesMixin from "./ImportModulesMixin.js";
4
- import OrigamiTransform from "./OrigamiTransform.js";
5
5
  import WatchFilesMixin from "./WatchFilesMixin.js";
6
6
 
7
- export default class OrigamiFiles extends OrigamiTransform(
7
+ export default class OrigamiFiles extends HandleExtensionsTransform(
8
8
  ImportModulesMixin(WatchFilesMixin(EventTargetMixin(FileTree)))
9
9
  ) {}
@@ -27,7 +27,7 @@ export default async function evaluate(code) {
27
27
  }
28
28
 
29
29
  let evaluated;
30
- const unevaluatedFns = [ops.lambda, ops.object, ops.tree];
30
+ const unevaluatedFns = [ops.lambda, ops.object];
31
31
  if (unevaluatedFns.includes(code[0])) {
32
32
  // Don't evaluate instructions, use as is.
33
33
  evaluated = code;
@@ -79,12 +79,7 @@ export default async function evaluate(code) {
79
79
  }
80
80
 
81
81
  // To aid debugging, add the code to the result.
82
- if (
83
- result &&
84
- typeof result === "object" &&
85
- Object.isExtensible(result) &&
86
- !isPlainObject(result)
87
- ) {
82
+ if (Object.isExtensible(result) && !isPlainObject(result)) {
88
83
  try {
89
84
  result[codeSymbol] = code;
90
85
  if (/** @type {any} */ (code).location) {
@@ -0,0 +1,103 @@
1
+ import { ObjectTree, symbols } from "@weborigami/async-tree";
2
+ import { attachHandlerIfApplicable, extname } from "./extensions.js";
3
+ import { evaluate, ops } from "./internal.js";
4
+
5
+ /**
6
+ * Given an array of entries with string keys and Origami code values (arrays of
7
+ * ops and operands), return an object with the same keys defining properties
8
+ * whose getters evaluate the code.
9
+ *
10
+ * The value can take three forms:
11
+ *
12
+ * 1. A primitive value (string, etc.). This will be defined directly as an
13
+ * object property.
14
+ * 1. An immediate code entry. This will be evaluated during this call and its
15
+ * result defined as an object property.
16
+ * 1. A code entry that starts with ops.getter. This will be defined as a
17
+ * property getter on the object.
18
+ *
19
+ * @param {*} entries
20
+ * @param {import("@weborigami/types").AsyncTree | null} parent
21
+ */
22
+ export default async function expressionObject(entries, parent) {
23
+ // Create the object and set its parent
24
+ const object = {};
25
+ Object.defineProperty(object, symbols.parent, {
26
+ value: parent,
27
+ writable: true,
28
+ configurable: true,
29
+ enumerable: false,
30
+ });
31
+
32
+ let tree;
33
+ const immediateProperties = [];
34
+ for (let [key, value] of entries) {
35
+ // Determine if we need to define a getter or a regular property. If the key
36
+ // has an extension, we need to define a getter. If the value is code (an
37
+ // array), we need to define a getter -- but if that code takes the form
38
+ // [ops.getter, <primitive>], we can define a regular property.
39
+
40
+ let defineProperty;
41
+ const extension = extname(key);
42
+ if (extension) {
43
+ defineProperty = false;
44
+ } else if (!(value instanceof Array)) {
45
+ defineProperty = true;
46
+ } else if (value[0] === ops.getter && !(value[1] instanceof Array)) {
47
+ defineProperty = true;
48
+ value = value[1];
49
+ } else {
50
+ defineProperty = false;
51
+ }
52
+
53
+ if (defineProperty) {
54
+ // Define simple property
55
+ object[key] = value;
56
+ } else {
57
+ // Property getter
58
+ let code;
59
+ if (value[0] === ops.getter) {
60
+ code = value[1];
61
+ } else {
62
+ immediateProperties.push(key);
63
+ code = value;
64
+ }
65
+
66
+ let get;
67
+ if (extension) {
68
+ // Key has extension, getter will invoke code then attach unpack method
69
+ get = async () => {
70
+ tree ??= new ObjectTree(object);
71
+ const result = await evaluate.call(tree, code);
72
+ return attachHandlerIfApplicable(tree, result, key);
73
+ };
74
+ } else {
75
+ // No extension, so getter just invokes code.
76
+ get = async () => {
77
+ tree ??= new ObjectTree(object);
78
+ return evaluate.call(tree, code);
79
+ };
80
+ }
81
+
82
+ Object.defineProperty(object, key, {
83
+ configurable: true,
84
+ enumerable: true,
85
+ get,
86
+ });
87
+ }
88
+ }
89
+
90
+ // Evaluate any properties that were declared as immediate: get their value
91
+ // and overwrite the property getter with the actual value.
92
+ for (const key of immediateProperties) {
93
+ const value = await object[key];
94
+ Object.defineProperty(object, key, {
95
+ configurable: true,
96
+ enumerable: true,
97
+ value,
98
+ writable: true,
99
+ });
100
+ }
101
+
102
+ return object;
103
+ }
@@ -0,0 +1,94 @@
1
+ import {
2
+ box,
3
+ isPacked,
4
+ isStringLike,
5
+ isUnpackable,
6
+ scope,
7
+ symbols,
8
+ toString,
9
+ } from "@weborigami/async-tree";
10
+
11
+ /**
12
+ * If the given value is packed (e.g., buffer) and the key is a string-like path
13
+ * that ends in an extension, search for a handler for that extension and, if
14
+ * found, attach it to the value.
15
+ *
16
+ * @param {import("@weborigami/types").AsyncTree} parent
17
+ * @param {any} value
18
+ * @param {any} key
19
+ */
20
+ export async function attachHandlerIfApplicable(parent, value, key) {
21
+ if (isPacked(value) && isStringLike(key)) {
22
+ key = toString(key);
23
+
24
+ // Special case: `.ori.<ext>` extensions are Origami documents.
25
+ const extension = key.match(/\.ori\.\S+$/) ? ".ori_document" : extname(key);
26
+ if (extension) {
27
+ const handler = await getExtensionHandler(parent, extension);
28
+ if (handler) {
29
+ // If the value is a primitive, box it so we can attach data to it.
30
+ value = box(value);
31
+
32
+ if (handler.mediaType) {
33
+ value.mediaType = handler.mediaType;
34
+ }
35
+ value[symbols.parent] = parent;
36
+
37
+ const unpack = handler.unpack;
38
+ if (unpack) {
39
+ // Wrap the unpack function so its only called once per value.
40
+ let loaded;
41
+ value.unpack = async () => {
42
+ loaded ??= await unpack(value, { key, parent });
43
+ return loaded;
44
+ };
45
+ }
46
+ }
47
+ }
48
+ }
49
+ return value;
50
+ }
51
+
52
+ /**
53
+ * Find an extension handler for a file in the given container.
54
+ *
55
+ * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
56
+ *
57
+ * @param {AsyncTree} parent
58
+ * @param {string} extension
59
+ */
60
+ export async function getExtensionHandler(parent, extension) {
61
+ const handlerName = `${extension.slice(1)}_handler`;
62
+ const parentScope = scope(parent);
63
+ /** @type {import("../../index.ts").ExtensionHandler} */
64
+ let extensionHandler = await parentScope?.get(handlerName);
65
+ if (isUnpackable(extensionHandler)) {
66
+ // The extension handler itself needs to be unpacked. E.g., if it's a
67
+ // buffer containing JavaScript file, we need to unpack it to get its
68
+ // default export.
69
+ // @ts-ignore
70
+ extensionHandler = await extensionHandler.unpack();
71
+ }
72
+ return extensionHandler;
73
+ }
74
+
75
+ /**
76
+ * If the given path ends in an extension, return it. Otherwise, return the
77
+ * empty string.
78
+ *
79
+ * This is meant as a basic replacement for the standard Node `path.extname`.
80
+ * That standard function inaccurately returns an extension for a path that
81
+ * includes a near-final extension but ends in a final slash, like `foo.txt/`.
82
+ * Node thinks that path has a ".txt" extension, but for our purposes it
83
+ * doesn't.
84
+ *
85
+ * @param {string} path
86
+ */
87
+ export function extname(path) {
88
+ // We want at least one character before the dot, then a dot, then a non-empty
89
+ // sequence of characters after the dot that aren't slahes or dots.
90
+ const extnameRegex = /[^/](?<ext>\.[^/\.]+)$/;
91
+ const match = String(path).match(extnameRegex);
92
+ const extension = match?.groups?.ext.toLowerCase() ?? "";
93
+ return extension;
94
+ }
@@ -12,7 +12,3 @@ export * as ops from "./ops.js";
12
12
  export { default as evaluate } from "./evaluate.js";
13
13
 
14
14
  export * as expressionFunction from "./expressionFunction.js";
15
-
16
- export { default as ExpressionTree } from "./ExpressionTree.js";
17
-
18
- export { default as OrigamiTree } from "./OrigamiTree.js";
@@ -11,11 +11,12 @@ import {
11
11
  scope as scopeFn,
12
12
  concat as treeConcat,
13
13
  } from "@weborigami/async-tree";
14
+ import expressionObject from "./expressionObject.js";
15
+ import { attachHandlerIfApplicable } from "./extensions.js";
14
16
  import HandleExtensionsTransform from "./HandleExtensionsTransform.js";
15
- import OrigamiFiles from "./OrigamiFiles.js";
16
- import handleExtension from "./handleExtension.js";
17
- import { OrigamiTree, evaluate, expressionFunction } from "./internal.js";
17
+ import { evaluate } from "./internal.js";
18
18
  import mergeTrees from "./mergeTrees.js";
19
+ import OrigamiFiles from "./OrigamiFiles.js";
19
20
 
20
21
  // For memoizing lambda functions
21
22
  const lambdaFnMap = new Map();
@@ -104,12 +105,18 @@ async function fetchResponse(href) {
104
105
  const url = new URL(href);
105
106
  const filename = url.pathname.split("/").pop();
106
107
  if (this && filename) {
107
- buffer = await handleExtension(this, filename, buffer);
108
+ buffer = await attachHandlerIfApplicable(this, buffer, filename);
108
109
  }
109
110
 
110
111
  return buffer;
111
112
  }
112
113
 
114
+ /**
115
+ * This op is only used during parsing. It signals to ops.object that the
116
+ * "arguments" of the expression should be used to define a property getter.
117
+ */
118
+ export const getter = new String("«ops.getter»");
119
+
113
120
  /**
114
121
  * Construct a files tree for the filesystem root.
115
122
  *
@@ -246,13 +253,7 @@ merge.toString = () => "«ops.merge»";
246
253
  * @param {any[]} entries
247
254
  */
248
255
  export async function object(...entries) {
249
- const tree = this;
250
- const promises = entries.map(async ([key, value]) => [
251
- key,
252
- await evaluate.call(tree, value),
253
- ]);
254
- const evaluated = await Promise.all(promises);
255
- return Object.fromEntries(evaluated);
256
+ return expressionObject(entries, this);
256
257
  }
257
258
  object.toString = () => "«ops.object»";
258
259
 
@@ -286,29 +287,6 @@ spread.toString = () => "«ops.spread»";
286
287
  */
287
288
  export const traverse = Tree.traverseOrThrow;
288
289
 
289
- /**
290
- * Construct an tree. This is similar to ops.object but the values are turned
291
- * into functions rather than being immediately evaluated, and the result is an
292
- * OrigamiTree.
293
- *
294
- * @this {AsyncTree|null}
295
- * @param {any[]} entries
296
- */
297
- export async function tree(...entries) {
298
- const fns = entries.map(([key, code]) => {
299
- const value =
300
- code instanceof Array
301
- ? expressionFunction.createExpressionFunction(code)
302
- : code;
303
- return [key, value];
304
- });
305
- const object = Object.fromEntries(fns);
306
- const result = new OrigamiTree(object);
307
- result.parent = this;
308
- return result;
309
- }
310
- tree.toString = () => "«ops.tree»";
311
-
312
290
  /**
313
291
  * A website tree via HTTP.
314
292
  *
@@ -1,4 +1,4 @@
1
- import { ObjectTree, Tree } from "@weborigami/async-tree";
1
+ import { ObjectTree, symbols, Tree } from "@weborigami/async-tree";
2
2
  import assert from "node:assert";
3
3
  import { describe, test } from "node:test";
4
4
  import * as compile from "../../src/compiler/compile.js";
@@ -24,7 +24,7 @@ describe("compile", () => {
24
24
  test("tree", async () => {
25
25
  const fn = compile.expression("{ message = greet(name) }");
26
26
  const tree = await fn.call(null);
27
- tree.parent = shared;
27
+ tree[symbols.parent] = shared;
28
28
  assert.deepEqual(await Tree.plain(tree), {
29
29
  message: "Hello, Alice!",
30
30
  });
@@ -24,22 +24,6 @@ describe("Origami parser", () => {
24
24
  ]);
25
25
  });
26
26
 
27
- test("treeAssignment", () => {
28
- assertParse("treeAssignment", "data = obj.json", [
29
- "data",
30
- [ops.scope, "obj.json"],
31
- ]);
32
- assertParse("treeAssignment", "foo = fn 'bar'", [
33
- "foo",
34
- [[ops.scope, "fn"], "bar"],
35
- ]);
36
- });
37
-
38
- test("treeEntry", () => {
39
- assertParse("treeEntry", "foo", ["foo", [ops.inherited, "foo"]]);
40
- assertParse("treeEntry", "foo = 1", ["foo", 1]);
41
- });
42
-
43
27
  test("expr", () => {
44
28
  assertParse("expr", "obj.json", [ops.scope, "obj.json"]);
45
29
  assertParse("expr", "(fn a, b, c)", [
@@ -93,20 +77,26 @@ describe("Origami parser", () => {
93
77
  }
94
78
  `,
95
79
  [
96
- ops.tree,
80
+ ops.object,
97
81
  [
98
82
  "index.html",
99
83
  [
100
- [ops.scope, "index.ori"],
101
- [ops.scope, "teamData.yaml"],
84
+ ops.getter,
85
+ [
86
+ [ops.scope, "index.ori"],
87
+ [ops.scope, "teamData.yaml"],
88
+ ],
102
89
  ],
103
90
  ],
104
91
  [
105
92
  "thumbnails",
106
93
  [
107
- [ops.scope, "@map"],
108
- [ops.scope, "images"],
109
- [ops.object, ["value", [ops.scope, "thumbnail.js"]]],
94
+ ops.getter,
95
+ [
96
+ [ops.scope, "@map"],
97
+ [ops.scope, "images"],
98
+ [ops.object, ["value", [ops.scope, "thumbnail.js"]]],
99
+ ],
110
100
  ],
111
101
  ],
112
102
  ]
@@ -297,13 +287,22 @@ describe("Origami parser", () => {
297
287
  assertParse("object", "{ a: 1, b }", [
298
288
  ops.object,
299
289
  ["a", 1],
300
- ["b", [ops.scope, "b"]],
290
+ ["b", [ops.inherited, "b"]],
301
291
  ]);
302
292
  assertParse("object", `{ "a": 1, "b": 2 }`, [
303
293
  ops.object,
304
294
  ["a", 1],
305
295
  ["b", 2],
306
296
  ]);
297
+ assertParse("object", "{ a = b, b: 2 }", [
298
+ ops.object,
299
+ ["a", [ops.getter, [ops.scope, "b"]]],
300
+ ["b", 2],
301
+ ]);
302
+ assertParse("object", "{ x = fn('a') }", [
303
+ ops.object,
304
+ ["x", [ops.getter, [[ops.scope, "fn"], "a"]]],
305
+ ]);
307
306
  assertParse("object", "{ a: 1, ...b }", [
308
307
  ops.merge,
309
308
  [ops.object, ["a", 1]],
@@ -311,6 +310,22 @@ describe("Origami parser", () => {
311
310
  ]);
312
311
  });
313
312
 
313
+ test("objectEntry", () => {
314
+ assertParse("objectEntry", "foo", ["foo", [ops.inherited, "foo"]]);
315
+ assertParse("objectEntry", "x: y", ["x", [ops.scope, "y"]]);
316
+ });
317
+
318
+ test("objectGetter", () => {
319
+ assertParse("objectGetter", "data = obj.json", [
320
+ "data",
321
+ [ops.getter, [ops.scope, "obj.json"]],
322
+ ]);
323
+ assertParse("objectGetter", "foo = fn 'bar'", [
324
+ "foo",
325
+ [ops.getter, [[ops.scope, "fn"], "bar"]],
326
+ ]);
327
+ });
328
+
314
329
  test("objectProperty", () => {
315
330
  assertParse("objectProperty", "a: 1", ["a", 1]);
316
331
  assertParse("objectProperty", "name: 'Alice'", ["name", "Alice"]);
@@ -320,11 +335,6 @@ describe("Origami parser", () => {
320
335
  ]);
321
336
  });
322
337
 
323
- test("objectEntry", () => {
324
- assertParse("objectEntry", "foo", ["foo", [ops.scope, "foo"]]);
325
- assertParse("objectEntry", "x: y", ["x", [ops.scope, "y"]]);
326
- });
327
-
328
338
  test("parameterizedLambda", () => {
329
339
  assertParse("parameterizedLambda", "() => foo", [
330
340
  ops.lambda,
@@ -496,24 +506,6 @@ describe("Origami parser", () => {
496
506
  assertParse("templateSubstitution", "${foo}", [ops.scope, "foo"]);
497
507
  });
498
508
 
499
- test("tree", () => {
500
- assertParse("tree", "{}", [ops.tree]);
501
- assertParse("tree", "{ a = 1, b }", [
502
- ops.tree,
503
- ["a", 1],
504
- ["b", [ops.inherited, "b"]],
505
- ]);
506
- assertParse("tree", "{ x = fn('a') }", [
507
- ops.tree,
508
- ["x", [[ops.scope, "fn"], "a"]],
509
- ]);
510
- assertParse("tree", "{ a = 1, ...b }", [
511
- ops.merge,
512
- [ops.tree, ["a", 1]],
513
- [ops.scope, "b"],
514
- ]);
515
- });
516
-
517
509
  test("whitespace block", () => {
518
510
  assertParse(
519
511
  "__",
@@ -0,0 +1,66 @@
1
+ import { ObjectTree, symbols, Tree } from "@weborigami/async-tree";
2
+ import assert from "node:assert";
3
+ import { describe, test } from "node:test";
4
+
5
+ import expressionObject from "../../src/runtime/expressionObject.js";
6
+ import { ops } from "../../src/runtime/internal.js";
7
+
8
+ describe("expressionObject", () => {
9
+ test("can instantiate an object", async () => {
10
+ const scope = new ObjectTree({
11
+ upper: (s) => s.toUpperCase(),
12
+ });
13
+
14
+ const entries = [
15
+ ["hello", [[ops.scope, "upper"], "hello"]],
16
+ ["world", [[ops.scope, "upper"], "world"]],
17
+ ];
18
+
19
+ const object = await expressionObject(entries, scope);
20
+ assert.equal(await object.hello, "HELLO");
21
+ assert.equal(await object.world, "WORLD");
22
+ assert.equal(object[symbols.parent], scope);
23
+ });
24
+
25
+ test("can define a property getter", async () => {
26
+ let count = 0;
27
+ const increment = () => count++;
28
+ const entries = [["count", [ops.getter, [increment]]]];
29
+ const object = await expressionObject(entries, null);
30
+ assert.equal(await object.count, 0);
31
+ assert.equal(await object.count, 1);
32
+ });
33
+
34
+ test("treats a getter for a primitive value as a regular property", async () => {
35
+ const entries = [["name", [ops.getter, "world"]]];
36
+ const object = await expressionObject(entries, null);
37
+ assert.equal(object.name, "world");
38
+ });
39
+
40
+ test("can instantiate an Origami tree", async () => {
41
+ const entries = [
42
+ ["name", "world"],
43
+ ["message", [ops.concat, "Hello, ", [ops.scope, "name"], "!"]],
44
+ ];
45
+ const parent = new ObjectTree({});
46
+ const object = await expressionObject(entries, parent);
47
+ assert.deepEqual(await Tree.plain(object), {
48
+ name: "world",
49
+ message: "Hello, world!",
50
+ });
51
+ assert.equal(object[symbols.parent], parent);
52
+ });
53
+
54
+ test("returned object values can be unpacked", async () => {
55
+ const entries = [["data.json", `{ "a": 1 }`]];
56
+ const parent = new ObjectTree({
57
+ json_handler: {
58
+ unpack: JSON.parse,
59
+ },
60
+ });
61
+ const result = await expressionObject(entries, parent);
62
+ const dataJson = await result["data.json"];
63
+ const json = await dataJson.unpack();
64
+ assert.deepEqual(json, { a: 1 });
65
+ });
66
+ });
@@ -0,0 +1,36 @@
1
+ import { ObjectTree } from "@weborigami/async-tree";
2
+ import assert from "node:assert";
3
+ import { describe, test } from "node:test";
4
+ import { attachHandlerIfApplicable } from "../../src/runtime/extensions.js";
5
+
6
+ describe("extensions", () => {
7
+ test("attaches an unpack method to a value with an extension", async () => {
8
+ const fixture = createFixture();
9
+ const numberValue = await fixture.get("foo");
10
+ assert(typeof numberValue === "number");
11
+ assert.equal(numberValue, 1);
12
+ const jsonFile = await fixture.get("bar.json");
13
+ const withHandler = await attachHandlerIfApplicable(
14
+ fixture,
15
+ jsonFile,
16
+ "bar.json"
17
+ );
18
+ assert.equal(String(withHandler), `{ "bar": 2 }`);
19
+ const data = await withHandler.unpack();
20
+ assert.deepEqual(data, { bar: 2 });
21
+ });
22
+ });
23
+
24
+ function createFixture() {
25
+ const parent = new ObjectTree({
26
+ json_handler: {
27
+ unpack: (buffer) => JSON.parse(String(buffer)),
28
+ },
29
+ });
30
+ let tree = new ObjectTree({
31
+ foo: 1, // No extension, should be left alone
32
+ "bar.json": `{ "bar": 2 }`,
33
+ });
34
+ tree.parent = parent;
35
+ return tree;
36
+ }
@@ -1,13 +1,8 @@
1
- import { ObjectTree, Tree } from "@weborigami/async-tree";
1
+ import { ObjectTree } from "@weborigami/async-tree";
2
2
  import assert from "node:assert";
3
3
  import { describe, test } from "node:test";
4
4
 
5
- import {
6
- OrigamiTree,
7
- evaluate,
8
- expressionFunction,
9
- ops,
10
- } from "../../src/runtime/internal.js";
5
+ import { evaluate, ops } from "../../src/runtime/internal.js";
11
6
 
12
7
  describe("ops", () => {
13
8
  test("can resolve substitutions in a template literal", async () => {
@@ -85,30 +80,6 @@ describe("ops", () => {
85
80
  assert.deepEqual(result, ["Hello", 1, "WORLD"]);
86
81
  });
87
82
 
88
- test("can instantiate an Origami tree", async () => {
89
- const code = [
90
- ops.tree,
91
- ["name", "world"],
92
- [
93
- "message",
94
- expressionFunction.createExpressionFunction([
95
- ops.concat,
96
- "Hello, ",
97
- [ops.scope, "name"],
98
- "!",
99
- ]),
100
- ],
101
- ];
102
- const parent = new ObjectTree({});
103
- const result = await evaluate.call(parent, code);
104
- assert(result instanceof OrigamiTree);
105
- assert.deepEqual(await Tree.plain(result), {
106
- name: "world",
107
- message: "Hello, world!",
108
- });
109
- assert.equal(result.parent, parent);
110
- });
111
-
112
83
  test("can search inherited scope", async () => {
113
84
  const parent = new ObjectTree({
114
85
  a: 1, // This is the inherited value we want
@@ -1,6 +0,0 @@
1
- import { DeepObjectTree } from "@weborigami/async-tree";
2
- import InvokeFunctionsTransform from "./InvokeFunctionsTransform.js";
3
-
4
- export default class ExpressionTree extends InvokeFunctionsTransform(
5
- DeepObjectTree
6
- ) {}
@@ -1,5 +0,0 @@
1
- import { Mixin } from "../../index.ts";
2
-
3
- declare const OrigamiTransform: Mixin<{}>;
4
-
5
- export default OrigamiTransform;
@@ -1,3 +0,0 @@
1
- // Right now this just applies HandleExtensionsTransform.
2
- import HandleExtensionsTransform from "./HandleExtensionsTransform.js";
3
- export default HandleExtensionsTransform;