@weborigami/language 0.0.71 → 0.0.73
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.0.
|
|
3
|
+
"version": "0.0.73",
|
|
4
4
|
"description": "Web Origami expression language compiler and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"typescript": "5.6.2"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.0.
|
|
15
|
-
"@weborigami/types": "0.0.
|
|
14
|
+
"@weborigami/async-tree": "0.0.73",
|
|
15
|
+
"@weborigami/types": "0.0.73",
|
|
16
16
|
"watcher": "2.3.1"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
package/src/compiler/compile.js
CHANGED
|
@@ -3,7 +3,9 @@ import { createExpressionFunction } from "../runtime/expressionFunction.js";
|
|
|
3
3
|
import { ops } from "../runtime/internal.js";
|
|
4
4
|
import { parse } from "./parse.js";
|
|
5
5
|
|
|
6
|
-
function compile(source,
|
|
6
|
+
function compile(source, options) {
|
|
7
|
+
const { startRule } = options;
|
|
8
|
+
const scopeCaching = options.scopeCaching ?? true;
|
|
7
9
|
if (typeof source === "string") {
|
|
8
10
|
source = { text: source };
|
|
9
11
|
}
|
|
@@ -12,20 +14,25 @@ function compile(source, startRule) {
|
|
|
12
14
|
startRule,
|
|
13
15
|
});
|
|
14
16
|
const cache = {};
|
|
15
|
-
const modified =
|
|
17
|
+
const modified = scopeCaching
|
|
18
|
+
? cacheExternalScopeReferences(code, cache)
|
|
19
|
+
: code;
|
|
16
20
|
// const modified = code;
|
|
17
21
|
const fn = createExpressionFunction(modified);
|
|
18
22
|
return fn;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
export function expression(source) {
|
|
22
|
-
return compile(source,
|
|
25
|
+
export function expression(source, options = {}) {
|
|
26
|
+
return compile(source, {
|
|
27
|
+
...options,
|
|
28
|
+
startRule: "expression",
|
|
29
|
+
});
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
// Given code containing ops.scope calls, upgrade them to ops.cache calls unless
|
|
26
33
|
// they refer to local variables: variables defined by object literals or lambda
|
|
27
34
|
// parameters.
|
|
28
|
-
export function
|
|
35
|
+
export function cacheExternalScopeReferences(code, cache, locals = {}) {
|
|
29
36
|
const [fn, ...args] = code;
|
|
30
37
|
|
|
31
38
|
let additionalLocalNames;
|
|
@@ -67,7 +74,7 @@ export function cacheNonLocalScopeReferences(code, cache, locals = {}) {
|
|
|
67
74
|
// be preferable to only descend into instructions. This would require
|
|
68
75
|
// surrounding ops.lambda parameters with ops.literal, and ops.object
|
|
69
76
|
// entries with ops.array.
|
|
70
|
-
return
|
|
77
|
+
return cacheExternalScopeReferences(child, cache, updatedLocals);
|
|
71
78
|
} else {
|
|
72
79
|
return child;
|
|
73
80
|
}
|
|
@@ -79,6 +86,9 @@ export function cacheNonLocalScopeReferences(code, cache, locals = {}) {
|
|
|
79
86
|
return modified;
|
|
80
87
|
}
|
|
81
88
|
|
|
82
|
-
export function templateDocument(source) {
|
|
83
|
-
return compile(source,
|
|
89
|
+
export function templateDocument(source, options = {}) {
|
|
90
|
+
return compile(source, {
|
|
91
|
+
...options,
|
|
92
|
+
startRule: "templateDocument",
|
|
93
|
+
});
|
|
84
94
|
}
|
|
@@ -53,7 +53,7 @@ export async function getExtensionHandler(parent, extension) {
|
|
|
53
53
|
handlersForContainer.set(parent, handlers);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
const handlerName = `${extension.slice(1)}
|
|
56
|
+
const handlerName = `${extension.slice(1)}.handler`;
|
|
57
57
|
const parentScope = scope(parent);
|
|
58
58
|
|
|
59
59
|
/** @type {Promise<ExtensionHandler>} */
|
|
@@ -95,7 +95,7 @@ export async function handleExtension(parent, value, key) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// Special case: `.ori.<ext>` extensions are Origami documents.
|
|
98
|
-
const extension = key.match(/\.ori\.\S+$/) ? ".
|
|
98
|
+
const extension = key.match(/\.ori\.\S+$/) ? ".oridocument" : extname(key);
|
|
99
99
|
if (extension) {
|
|
100
100
|
const handler = await getExtensionHandler(parent, extension);
|
|
101
101
|
if (handler) {
|
package/src/runtime/ops.js
CHANGED
|
@@ -54,7 +54,7 @@ describe("expressionObject", () => {
|
|
|
54
54
|
test("returned object values can be unpacked", async () => {
|
|
55
55
|
const entries = [["data.json", `{ "a": 1 }`]];
|
|
56
56
|
const parent = new ObjectTree({
|
|
57
|
-
|
|
57
|
+
"json.handler": {
|
|
58
58
|
unpack: JSON.parse,
|
|
59
59
|
},
|
|
60
60
|
});
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -5,6 +5,12 @@ import { describe, test } from "node:test";
|
|
|
5
5
|
import { evaluate, ops } from "../../src/runtime/internal.js";
|
|
6
6
|
|
|
7
7
|
describe("ops", () => {
|
|
8
|
+
test("ops.array creates an array", async () => {
|
|
9
|
+
const code = createCode([ops.array, 1, 2, 3]);
|
|
10
|
+
const result = await evaluate.call(null, code);
|
|
11
|
+
assert.deepEqual(result, [1, 2, 3]);
|
|
12
|
+
});
|
|
13
|
+
|
|
8
14
|
test("ops.cache looks up a value in scope and memoizes it", async () => {
|
|
9
15
|
let count = 0;
|
|
10
16
|
const tree = new ObjectTree({
|