@weborigami/language 0.0.43 → 0.0.44

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/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { AsyncTree } from "@weborigami/types";
2
- import { StringLike } from "../async-tree/index.js";
3
1
 
4
2
  export * from "./main.js";
5
3
 
@@ -19,15 +17,12 @@ export type Code = ArrayWithSource;
19
17
  export type Constructor<T> = new (...args: any[]) => T;
20
18
 
21
19
  /**
22
- * A function that can convert a string-like input value into some live object.
20
+ * A function that can convert a value from some persistent form into some kind
21
+ * of live value.
23
22
  */
24
23
  export type FileUnpackFunction = (
25
- input: StringLike,
26
- options?: {
27
- compiler?: any,
28
- key?: any,
29
- parent?: AsyncTree | null
30
- }
24
+ input: any,
25
+ options?: any
31
26
  ) => any;
32
27
 
33
28
  /**
package/main.js CHANGED
@@ -19,3 +19,4 @@ export * as expressionFunction from "./src/runtime/expressionFunction.js";
19
19
  export { default as extname } from "./src/runtime/extname.js";
20
20
  export { default as formatError } from "./src/runtime/formatError.js";
21
21
  export { default as functionResultsMap } from "./src/runtime/functionResultsMap.js";
22
+ export * as symbols from "./src/runtime/symbols.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -10,8 +10,8 @@
10
10
  "typescript": "5.3.3"
11
11
  },
12
12
  "dependencies": {
13
- "@weborigami/async-tree": "0.0.43",
14
- "@weborigami/types": "0.0.43",
13
+ "@weborigami/async-tree": "0.0.44",
14
+ "@weborigami/types": "0.0.44",
15
15
  "peggy": "3.0.2",
16
16
  "watcher": "2.3.0"
17
17
  },
@@ -1,6 +1,7 @@
1
1
  import { Tree, isStringLike } from "@weborigami/async-tree";
2
2
  import Scope from "./Scope.js";
3
3
  import extname from "./extname.js";
4
+ import * as symbols from "./symbols.js";
4
5
 
5
6
  /**
6
7
  * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
@@ -14,25 +15,31 @@ export default function FileLoadersTransform(Base) {
14
15
  async get(key) {
15
16
  let value = await super.get(key);
16
17
 
17
- // If the value is string-like and the key has an extension, look for a
18
- // loader that handles that extension and call it. The value will
19
- // typically be a Buffer loaded from the file system, but could also be a
20
- // string-like object defined by a user function.
21
- if (isStringLike(value) && isStringLike(key)) {
18
+ // If the key is string-like and has an extension, look for a loader that
19
+ // handles that extension.
20
+ if (value && isStringLike(key)) {
22
21
  const extension = extname(String(key)).toLowerCase().slice(1);
23
22
  if (extension) {
24
23
  /** @type {any} */
25
24
  const scope = Scope.getScope(this);
26
- /** @type {FileUnpackFunction} */
27
- const unpackFn = await Tree.traverse(scope, "@loaders", extension);
28
- if (unpackFn) {
25
+ const loader = await Tree.traverse(scope, "@loaders", extension);
26
+ if (loader) {
29
27
  const input = value;
30
28
  // If the input is a plain string, convert it to a String so we can
31
29
  // attach data to it.
32
- value = new String(input);
30
+ if (typeof input === "string") {
31
+ value = new String(input);
32
+ }
33
33
  const parent = this;
34
- value.parent = parent;
35
- value.unpack = unpackFn.bind(null, input, { key, parent });
34
+ value[symbols.parent] = parent;
35
+
36
+ // Wrap the loader with a function that will only be called once per
37
+ // value.
38
+ let loaded;
39
+ value.unpack = async () => {
40
+ loaded ??= await loader(input, { key, parent });
41
+ return loaded;
42
+ };
36
43
  }
37
44
  }
38
45
  }
@@ -81,9 +81,13 @@ export default async function evaluate(code) {
81
81
  Object.isExtensible(result) &&
82
82
  !isPlainObject(result)
83
83
  ) {
84
- result[codeSymbol] = code;
85
- if (/** @type {any} */ (code).location) {
86
- result[sourceSymbol] = codeFragment(code);
84
+ try {
85
+ result[codeSymbol] = code;
86
+ if (/** @type {any} */ (code).location) {
87
+ result[sourceSymbol] = codeFragment(code);
88
+ }
89
+ } catch (/** @type {any} */ error) {
90
+ // Ignore errors.
87
91
  }
88
92
  }
89
93
 
@@ -0,0 +1 @@
1
+ export const parent = Symbol("parent");
@@ -33,7 +33,7 @@ function createFixture() {
33
33
  /** @type {any} */
34
34
  const scope = {
35
35
  "@loaders": {
36
- json: (input) => JSON.parse(input),
36
+ json: (buffer) => JSON.parse(String(buffer)),
37
37
  },
38
38
  };
39
39
  tree = Scope.treeWithScope(tree, scope);