@fraczak/k 8.0.0 → 8.1.0
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/CHANGELOG.md +24 -0
- package/DOCS/CODECS.md +22 -24
- package/DOCS/CODEC_ARCHITECTURE.md +3 -5
- package/DOCS/JSON_APPROACHES_COMPARISON.md +9 -13
- package/DOCS/WEB_REPL_REQUIREMENTS.md +3 -4
- package/Examples/djson.k +631 -165
- package/README.md +1 -3
- package/browser/repl-browser.mjs +0 -4
- package/browser/vfs-data.mjs +3 -9
- package/codecs/README.md +1 -3
- package/codecs/djson.mjs +375 -84
- package/package.json +1 -4
- package/scripts/build-repl-html.mjs +1 -11
- package/scripts/run-tests.mjs +5 -0
- package/tests/test-codecs.mjs +4 -34
- package/tests/test-djson-methods.mjs +285 -0
- package/tests/test-repl-html.mjs +0 -4
- package/tests/test-repl.mjs +14 -55
- package/Examples/djson-btrie.k +0 -414
- package/Examples/djson-ptrie.k +0 -663
- package/codecs/djson-btrie.mjs +0 -560
- package/codecs/djson-ptrie.mjs +0 -587
- package/scripts/perf-djson.mjs +0 -1142
- package/tests/bench-djson-tries.mjs +0 -340
package/tests/test-codecs.mjs
CHANGED
|
@@ -9,8 +9,6 @@ import * as SDK from "../codecs/runtime/codec-sdk.mjs";
|
|
|
9
9
|
import * as IntCodec from "../codecs/int.mjs";
|
|
10
10
|
import * as JsonCodec from "../codecs/json.mjs";
|
|
11
11
|
import * as DjsonCodec from "../codecs/djson.mjs";
|
|
12
|
-
import * as DjsonBtrieCodec from "../codecs/djson-btrie.mjs";
|
|
13
|
-
import * as DjsonPtrieCodec from "../codecs/djson-ptrie.mjs";
|
|
14
12
|
import * as Utf8Codec from "../codecs/utf8.mjs";
|
|
15
13
|
import * as Utf16Codec from "../codecs/utf16.mjs";
|
|
16
14
|
import * as IeeeCodec from "../codecs/ieee.mjs";
|
|
@@ -57,16 +55,6 @@ for (const [name, codec, sampleInput] of [
|
|
|
57
55
|
["int.mjs", IntCodec, "42"],
|
|
58
56
|
["json.mjs", JsonCodec, '{"x": 1}'],
|
|
59
57
|
["djson.mjs", DjsonCodec, '{"x": 1, "arr": [true, null, "hi"]}'],
|
|
60
|
-
[
|
|
61
|
-
"djson-btrie.mjs",
|
|
62
|
-
DjsonBtrieCodec,
|
|
63
|
-
'{"x": 1, "arr": [true, null, "hi"]}'
|
|
64
|
-
],
|
|
65
|
-
[
|
|
66
|
-
"djson-ptrie.mjs",
|
|
67
|
-
DjsonPtrieCodec,
|
|
68
|
-
'{"x": 1, "arr": [true, null, "hi"]}'
|
|
69
|
-
],
|
|
70
58
|
["utf8.mjs", Utf8Codec, "hello"],
|
|
71
59
|
["utf16.mjs", Utf16Codec, "hello"],
|
|
72
60
|
["ieee.mjs", IeeeCodec, "3.14"],
|
|
@@ -87,8 +75,6 @@ for (const relPath of [
|
|
|
87
75
|
"codecs/int.mjs",
|
|
88
76
|
"codecs/json.mjs",
|
|
89
77
|
"codecs/djson.mjs",
|
|
90
|
-
"codecs/djson-btrie.mjs",
|
|
91
|
-
"codecs/djson-ptrie.mjs",
|
|
92
78
|
"codecs/utf8.mjs",
|
|
93
79
|
"codecs/utf16.mjs",
|
|
94
80
|
"codecs/ieee.mjs",
|
|
@@ -328,15 +314,11 @@ console.log("8. Verifying fast string decoding & bounded rendering...");
|
|
|
328
314
|
);
|
|
329
315
|
}
|
|
330
316
|
|
|
331
|
-
// 9. DJSON
|
|
332
|
-
console.log("9. Verifying DJSON
|
|
317
|
+
// 9. DJSON Singleton Pattern Invariants & Round-Trip
|
|
318
|
+
console.log("9. Verifying DJSON singleton pattern invariants...");
|
|
333
319
|
{
|
|
334
320
|
assert(Array.isArray(DjsonCodec.DJSON_PATTERN));
|
|
335
|
-
assert.equal(DjsonCodec.DJSON_PATTERN.length,
|
|
336
|
-
assert(Array.isArray(DjsonBtrieCodec.DJSON_BTRIE_PATTERN));
|
|
337
|
-
assert.equal(DjsonBtrieCodec.DJSON_BTRIE_PATTERN.length, 27);
|
|
338
|
-
assert(Array.isArray(DjsonPtrieCodec.DJSON_PTRIE_PATTERN));
|
|
339
|
-
assert.equal(DjsonPtrieCodec.DJSON_PTRIE_PATTERN.length, 33);
|
|
321
|
+
assert.equal(DjsonCodec.DJSON_PATTERN.length, 27);
|
|
340
322
|
|
|
341
323
|
const samples = [
|
|
342
324
|
null,
|
|
@@ -351,19 +333,7 @@ console.log("9. Verifying DJSON family singleton pattern invariants...");
|
|
|
351
333
|
];
|
|
352
334
|
|
|
353
335
|
for (const [label, codec, pat, relPath] of [
|
|
354
|
-
["djson", DjsonCodec, DjsonCodec.DJSON_PATTERN, "codecs/djson.mjs"]
|
|
355
|
-
[
|
|
356
|
-
"djson-btrie",
|
|
357
|
-
DjsonBtrieCodec,
|
|
358
|
-
DjsonBtrieCodec.DJSON_BTRIE_PATTERN,
|
|
359
|
-
"codecs/djson-btrie.mjs"
|
|
360
|
-
],
|
|
361
|
-
[
|
|
362
|
-
"djson-ptrie",
|
|
363
|
-
DjsonPtrieCodec,
|
|
364
|
-
DjsonPtrieCodec.DJSON_PTRIE_PATTERN,
|
|
365
|
-
"codecs/djson-ptrie.mjs"
|
|
366
|
-
]
|
|
336
|
+
["djson", DjsonCodec, DjsonCodec.DJSON_PATTERN, "codecs/djson.mjs"]
|
|
367
337
|
]) {
|
|
368
338
|
for (const sample of samples) {
|
|
369
339
|
const jsonStr = JSON.stringify(sample);
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// tests/test-djson-methods.mjs
|
|
2
|
+
// Test suite for standard dynamic JSON methods working on json? type.
|
|
3
|
+
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
import k from "../index.mjs";
|
|
10
|
+
import { Value } from "../Value.mjs";
|
|
11
|
+
import {
|
|
12
|
+
fromJsonValue,
|
|
13
|
+
toJsonValue
|
|
14
|
+
} from "../codecs/djson.mjs";
|
|
15
|
+
import {
|
|
16
|
+
textToStringValue,
|
|
17
|
+
stringValueToText
|
|
18
|
+
} from "../codecs/runtime/unicode-string.mjs";
|
|
19
|
+
|
|
20
|
+
const root = path.resolve(
|
|
21
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
22
|
+
".."
|
|
23
|
+
);
|
|
24
|
+
const libPath = path.join(root, "Examples", "djson.k");
|
|
25
|
+
const djsonK = readFileSync(libPath, "utf8");
|
|
26
|
+
|
|
27
|
+
function compileOp(op) {
|
|
28
|
+
return k.compile(`${djsonK}\n${op}\n`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeIndex(n) {
|
|
32
|
+
if (n === 0) {
|
|
33
|
+
return Value.variant(
|
|
34
|
+
"0",
|
|
35
|
+
Value.variant("_", Value.product({}))
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const s = n.toString(2);
|
|
39
|
+
let v = Value.variant("_", Value.product({}));
|
|
40
|
+
for (let i = s.length - 1; i >= 0; i--) {
|
|
41
|
+
v = Value.variant(s[i], v);
|
|
42
|
+
}
|
|
43
|
+
return v;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log("==> Running Dynamic JSON (json?) Methods Test Suite");
|
|
47
|
+
|
|
48
|
+
// Test 1: Object Accessors (get, has?, set, del)
|
|
49
|
+
console.log("--> Test 1: Object Accessors (get, has?, set, del)");
|
|
50
|
+
{
|
|
51
|
+
const fnGet = compileOp("get");
|
|
52
|
+
const fnHas = compileOp("has?");
|
|
53
|
+
const fnSet = compileOp("set");
|
|
54
|
+
const fnDel = compileOp("del");
|
|
55
|
+
|
|
56
|
+
const doc = {
|
|
57
|
+
name: "Alice",
|
|
58
|
+
age: 30,
|
|
59
|
+
tags: ["developer", "k"]
|
|
60
|
+
};
|
|
61
|
+
const kDoc = fromJsonValue(doc);
|
|
62
|
+
|
|
63
|
+
// get "name"
|
|
64
|
+
const resName = fnGet(Value.product({
|
|
65
|
+
key: textToStringValue("name"),
|
|
66
|
+
json: kDoc
|
|
67
|
+
}));
|
|
68
|
+
assert.equal(toJsonValue(resName), "Alice");
|
|
69
|
+
|
|
70
|
+
// get "age"
|
|
71
|
+
const resAge = fnGet(Value.product({
|
|
72
|
+
key: textToStringValue("age"),
|
|
73
|
+
json: kDoc
|
|
74
|
+
}));
|
|
75
|
+
assert.equal(toJsonValue(resAge), 30);
|
|
76
|
+
|
|
77
|
+
// has? hit
|
|
78
|
+
const hit = fnHas(Value.product({
|
|
79
|
+
key: textToStringValue("name"),
|
|
80
|
+
json: kDoc
|
|
81
|
+
}));
|
|
82
|
+
assert.ok(hit);
|
|
83
|
+
|
|
84
|
+
// has? miss
|
|
85
|
+
const miss = fnHas(Value.product({
|
|
86
|
+
key: textToStringValue("missing"),
|
|
87
|
+
json: kDoc
|
|
88
|
+
}));
|
|
89
|
+
assert.equal(miss, undefined);
|
|
90
|
+
|
|
91
|
+
// set "city" = "Paris"
|
|
92
|
+
const withCity = fnSet(Value.product({
|
|
93
|
+
key: textToStringValue("city"),
|
|
94
|
+
val: fromJsonValue("Paris"),
|
|
95
|
+
json: kDoc
|
|
96
|
+
}));
|
|
97
|
+
assert.equal(toJsonValue(withCity).city, "Paris");
|
|
98
|
+
assert.equal(toJsonValue(withCity).name, "Alice");
|
|
99
|
+
|
|
100
|
+
// del "age"
|
|
101
|
+
const withoutAge = fnDel(Value.product({
|
|
102
|
+
key: textToStringValue("age"),
|
|
103
|
+
json: withCity
|
|
104
|
+
}));
|
|
105
|
+
assert.equal(toJsonValue(withoutAge).age, undefined);
|
|
106
|
+
assert.equal(toJsonValue(withoutAge).city, "Paris");
|
|
107
|
+
|
|
108
|
+
console.log(" Passed: Object get, has?, set, del on json?.");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Test 2: List Accessors (nth, has_index?, set_nth, del_nth, push)
|
|
112
|
+
console.log("--> Test 2: List Accessors (nth, set_nth, del_nth, push)");
|
|
113
|
+
{
|
|
114
|
+
const fnNth = compileOp("nth");
|
|
115
|
+
const fnHasIdx = compileOp("has_index?");
|
|
116
|
+
const fnSetNth = compileOp("set_nth");
|
|
117
|
+
const fnDelNth = compileOp("del_nth");
|
|
118
|
+
const fnPush = compileOp("push");
|
|
119
|
+
|
|
120
|
+
const list = [10, 20, 30];
|
|
121
|
+
const kList = fromJsonValue(list);
|
|
122
|
+
|
|
123
|
+
// nth 0, 1, 2
|
|
124
|
+
assert.equal(
|
|
125
|
+
toJsonValue(fnNth(Value.product({
|
|
126
|
+
index: makeIndex(0),
|
|
127
|
+
json: kList
|
|
128
|
+
}))),
|
|
129
|
+
10
|
|
130
|
+
);
|
|
131
|
+
assert.equal(
|
|
132
|
+
toJsonValue(fnNth(Value.product({
|
|
133
|
+
index: makeIndex(1),
|
|
134
|
+
json: kList
|
|
135
|
+
}))),
|
|
136
|
+
20
|
|
137
|
+
);
|
|
138
|
+
assert.equal(
|
|
139
|
+
toJsonValue(fnNth(Value.product({
|
|
140
|
+
index: makeIndex(2),
|
|
141
|
+
json: kList
|
|
142
|
+
}))),
|
|
143
|
+
30
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// has_index? hit and miss
|
|
147
|
+
assert.ok(fnHasIdx(Value.product({
|
|
148
|
+
index: makeIndex(1),
|
|
149
|
+
json: kList
|
|
150
|
+
})));
|
|
151
|
+
assert.equal(
|
|
152
|
+
fnHasIdx(Value.product({
|
|
153
|
+
index: makeIndex(99),
|
|
154
|
+
json: kList
|
|
155
|
+
})),
|
|
156
|
+
undefined
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// set_nth 1 -> 99
|
|
160
|
+
const updatedList = fnSetNth(Value.product({
|
|
161
|
+
index: makeIndex(1),
|
|
162
|
+
val: fromJsonValue(99),
|
|
163
|
+
json: kList
|
|
164
|
+
}));
|
|
165
|
+
assert.deepEqual(toJsonValue(updatedList), [10, 99, 30]);
|
|
166
|
+
|
|
167
|
+
// del_nth 1
|
|
168
|
+
const delList = fnDelNth(Value.product({
|
|
169
|
+
index: makeIndex(1),
|
|
170
|
+
json: updatedList
|
|
171
|
+
}));
|
|
172
|
+
assert.deepEqual(toJsonValue(delList), [10, 30]);
|
|
173
|
+
assert.equal(
|
|
174
|
+
fnHasIdx(Value.product({
|
|
175
|
+
index: makeIndex(1),
|
|
176
|
+
json: delList
|
|
177
|
+
})),
|
|
178
|
+
undefined
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// push 40
|
|
182
|
+
const pushed = fnPush(Value.product({
|
|
183
|
+
val: fromJsonValue(40),
|
|
184
|
+
json: kList
|
|
185
|
+
}));
|
|
186
|
+
assert.deepEqual(toJsonValue(pushed), [10, 20, 30, 40]);
|
|
187
|
+
|
|
188
|
+
console.log(" Passed: List nth, set_nth, del_nth, push on json?.");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Test 3: Keys and Values (keys, keys_raw, values, values_raw)
|
|
192
|
+
console.log("--> Test 3: Keys and Values (keys, values)");
|
|
193
|
+
{
|
|
194
|
+
const fnKeys = compileOp("keys");
|
|
195
|
+
const fnKeysRaw = compileOp("keys_raw");
|
|
196
|
+
const fnValues = compileOp("values");
|
|
197
|
+
const fnValuesRaw = compileOp("values_raw");
|
|
198
|
+
|
|
199
|
+
const doc = { b: 2, a: 1, c: 3 };
|
|
200
|
+
const kDoc = fromJsonValue(doc);
|
|
201
|
+
|
|
202
|
+
// keys (json? list of string)
|
|
203
|
+
const resKeys = fnKeys(kDoc);
|
|
204
|
+
assert.deepEqual(toJsonValue(resKeys), ["a", "b", "c"]);
|
|
205
|
+
|
|
206
|
+
// keys_raw (raw K cons-list of strings)
|
|
207
|
+
const resKeysRaw = fnKeysRaw(kDoc);
|
|
208
|
+
const rawKeyStrings = [];
|
|
209
|
+
let curr = resKeysRaw;
|
|
210
|
+
while (curr && curr.type === "<>" && curr.tag === "cons") {
|
|
211
|
+
rawKeyStrings.push(stringValueToText(curr.value.product.car));
|
|
212
|
+
curr = curr.value.product.cdr;
|
|
213
|
+
}
|
|
214
|
+
assert.deepEqual(rawKeyStrings, ["a", "b", "c"]);
|
|
215
|
+
|
|
216
|
+
// values on object (json? list of values)
|
|
217
|
+
const resValues = fnValues(kDoc);
|
|
218
|
+
assert.deepEqual(toJsonValue(resValues), [1, 2, 3]);
|
|
219
|
+
|
|
220
|
+
// values on list (json? identity)
|
|
221
|
+
const listJson = fromJsonValue([100, 200]);
|
|
222
|
+
assert.deepEqual(toJsonValue(fnValues(listJson)), [100, 200]);
|
|
223
|
+
|
|
224
|
+
console.log(" Passed: Keys and values extraction on json?.");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Test 4: Cardinality and Length (length, length_nat)
|
|
228
|
+
console.log("--> Test 4: Cardinality and Length (length, length_nat)");
|
|
229
|
+
{
|
|
230
|
+
const fnLength = compileOp("length");
|
|
231
|
+
|
|
232
|
+
const kObj = fromJsonValue({ x: 1, y: 2, z: 3, w: 4 });
|
|
233
|
+
const kArr = fromJsonValue(["a", "b", "c"]);
|
|
234
|
+
const kStr = fromJsonValue("hello");
|
|
235
|
+
|
|
236
|
+
// length returns json? number (float64)
|
|
237
|
+
assert.equal(toJsonValue(fnLength(kObj)), 4);
|
|
238
|
+
assert.equal(toJsonValue(fnLength(kArr)), 3);
|
|
239
|
+
assert.equal(toJsonValue(fnLength(kStr)), 5);
|
|
240
|
+
|
|
241
|
+
console.log(
|
|
242
|
+
" Passed: Length queries on json? object, list, string."
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Test 5: Type Predicates and type_of
|
|
247
|
+
console.log("--> Test 5: Type Predicates and type_of");
|
|
248
|
+
{
|
|
249
|
+
const fnTypeOf = compileOp("type_of");
|
|
250
|
+
const fnIsObj = compileOp("is_object?");
|
|
251
|
+
const fnIsList = compileOp("is_list?");
|
|
252
|
+
const fnIsStr = compileOp("is_string?");
|
|
253
|
+
const fnIsNum = compileOp("is_number?");
|
|
254
|
+
const fnIsBool = compileOp("is_bool?");
|
|
255
|
+
const fnIsNull = compileOp("is_null?");
|
|
256
|
+
|
|
257
|
+
const kObj = fromJsonValue({ a: 1 });
|
|
258
|
+
const kArr = fromJsonValue([1, 2]);
|
|
259
|
+
const kStr = fromJsonValue("hi");
|
|
260
|
+
const kNum = fromJsonValue(3.14);
|
|
261
|
+
const kBool = fromJsonValue(true);
|
|
262
|
+
const kNull = fromJsonValue(null);
|
|
263
|
+
|
|
264
|
+
assert.equal(fnTypeOf(kObj).tag, "object");
|
|
265
|
+
assert.equal(fnTypeOf(kArr).tag, "list");
|
|
266
|
+
assert.equal(fnTypeOf(kStr).tag, "string");
|
|
267
|
+
assert.equal(fnTypeOf(kNum).tag, "number");
|
|
268
|
+
assert.equal(fnTypeOf(kBool).tag, "bool");
|
|
269
|
+
assert.equal(fnTypeOf(kNull).tag, "null");
|
|
270
|
+
|
|
271
|
+
assert.ok(fnIsObj(kObj));
|
|
272
|
+
assert.equal(fnIsObj(kArr), undefined);
|
|
273
|
+
|
|
274
|
+
assert.ok(fnIsList(kArr));
|
|
275
|
+
assert.equal(fnIsList(kObj), undefined);
|
|
276
|
+
|
|
277
|
+
assert.ok(fnIsStr(kStr));
|
|
278
|
+
assert.ok(fnIsNum(kNum));
|
|
279
|
+
assert.ok(fnIsBool(kBool));
|
|
280
|
+
assert.ok(fnIsNull(kNull));
|
|
281
|
+
|
|
282
|
+
console.log(" Passed: Type predicates and type_of inspection.");
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
console.log("==> All Dynamic JSON Methods Tests Passed Successfully!");
|
package/tests/test-repl-html.mjs
CHANGED
package/tests/test-repl.mjs
CHANGED
|
@@ -581,74 +581,33 @@ assert.equal(output[0], "output limit disabled");
|
|
|
581
581
|
output = await evaluateInput(":limit", limitState);
|
|
582
582
|
assert.equal(output[0], "Current output limit: none");
|
|
583
583
|
|
|
584
|
-
// Verify Examples/djson.k (json?,
|
|
585
|
-
const
|
|
586
|
-
output = await evaluateInput(":load Examples/djson.k",
|
|
584
|
+
// Verify Examples/djson.k (json?, get, nth, set, del)
|
|
585
|
+
const djsonKState = createState({ engine: "wasm" });
|
|
586
|
+
output = await evaluateInput(":load Examples/djson.k", djsonKState);
|
|
587
587
|
assert.equal(output[0], "loaded Examples/djson.k");
|
|
588
|
-
await evaluateInput(":codec load codecs/djson.mjs",
|
|
588
|
+
await evaluateInput(":codec load codecs/djson.mjs", djsonKState);
|
|
589
589
|
await evaluateInput(
|
|
590
|
-
':input djson.mjs {"name":"Alice","age":30
|
|
591
|
-
|
|
590
|
+
':input djson.mjs ["age", {"name":"Alice","age":30}]',
|
|
591
|
+
djsonKState
|
|
592
592
|
);
|
|
593
593
|
output = await evaluateInput(
|
|
594
|
-
"{
|
|
595
|
-
|
|
594
|
+
"{{0 index, () json} nth /string key, " +
|
|
595
|
+
"{1 index, () json} nth json} get",
|
|
596
|
+
djsonKState
|
|
596
597
|
);
|
|
597
598
|
assert.match(output[0], /djson\.mjs: 30/);
|
|
598
599
|
|
|
599
600
|
await evaluateInput(
|
|
600
|
-
':input djson.mjs {"name":"Alice","age":30}',
|
|
601
|
-
|
|
601
|
+
':input djson.mjs ["age", {"name":"Alice","age":30}]',
|
|
602
|
+
djsonKState
|
|
602
603
|
);
|
|
603
604
|
output = await evaluateInput(
|
|
604
|
-
"{
|
|
605
|
-
|
|
605
|
+
"{{0 index, () json} nth /string key, " +
|
|
606
|
+
"{1 index, () json} nth json} del",
|
|
607
|
+
djsonKState
|
|
606
608
|
);
|
|
607
609
|
assert.match(output[0], /djson\.mjs: \{"name":"Alice"\}/);
|
|
608
610
|
|
|
609
|
-
// Verify Examples/djson-btrie.k (json?, dot, nth, put, remove)
|
|
610
|
-
const btrieState = createState({ engine: "wasm" });
|
|
611
|
-
output = await evaluateInput(":load Examples/djson-btrie.k", btrieState);
|
|
612
|
-
assert.equal(output[0], "loaded Examples/djson-btrie.k");
|
|
613
|
-
await evaluateInput(":codec load codecs/djson-btrie.mjs", btrieState);
|
|
614
|
-
await evaluateInput(
|
|
615
|
-
':input djson-btrie.mjs ["age", {"name":"Alice","age":30}]',
|
|
616
|
-
btrieState
|
|
617
|
-
);
|
|
618
|
-
output = await evaluateInput(
|
|
619
|
-
"{{0 index, /list list} nth /string key, " +
|
|
620
|
-
"{1 index, /list list} nth /object object} dot",
|
|
621
|
-
btrieState
|
|
622
|
-
);
|
|
623
|
-
assert.match(output[0], /djson-btrie\.mjs: 30/);
|
|
624
|
-
|
|
625
|
-
await evaluateInput(
|
|
626
|
-
':input djson-btrie.mjs ["age", {"name":"Alice","age":30}]',
|
|
627
|
-
btrieState
|
|
628
|
-
);
|
|
629
|
-
output = await evaluateInput(
|
|
630
|
-
"{{0 index, /list list} nth /string key, " +
|
|
631
|
-
"{1 index, /list list} nth /object object} remove object",
|
|
632
|
-
btrieState
|
|
633
|
-
);
|
|
634
|
-
assert.match(output[0], /djson-btrie\.mjs: \{"name":"Alice"\}/);
|
|
635
|
-
|
|
636
|
-
// Verify Examples/djson-ptrie.k (json?, dot, nth, list_size, obj_size)
|
|
637
|
-
const ptrieState = createState({ engine: "wasm" });
|
|
638
|
-
output = await evaluateInput(":load Examples/djson-ptrie.k", ptrieState);
|
|
639
|
-
assert.equal(output[0], "loaded Examples/djson-ptrie.k");
|
|
640
|
-
await evaluateInput(":codec load codecs/djson-ptrie.mjs", ptrieState);
|
|
641
|
-
await evaluateInput(
|
|
642
|
-
':input djson-ptrie.mjs ["age", {"name":"Alice","age":30}]',
|
|
643
|
-
ptrieState
|
|
644
|
-
);
|
|
645
|
-
output = await evaluateInput(
|
|
646
|
-
"{{0 index, /list list} nth /string key, " +
|
|
647
|
-
"{1 index, /list list} nth /object object} dot",
|
|
648
|
-
ptrieState
|
|
649
|
-
);
|
|
650
|
-
assert.match(output[0], /djson-ptrie\.mjs: 30/);
|
|
651
|
-
|
|
652
611
|
// Verify named pattern persistence, listing, display, and tab completion
|
|
653
612
|
const patState = createState({ engine: "wasm" });
|
|
654
613
|
|