@patterkit/runtime 0.20.0 → 0.21.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 +16 -0
- package/dist/index.cjs +22 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +22 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -33,6 +33,22 @@ version number always means the same runtime behaviour. This package is versione
|
|
|
33
33
|
|
|
34
34
|
## [Unreleased]
|
|
35
35
|
|
|
36
|
+
## [0.21.0] - 2026-10-07
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **A new `Engine` on a bundle another engine already uses no longer rebuilds the tag index.** It is built once
|
|
41
|
+
per bundle and shared, so a tool that starts a fresh engine for every run (coverage does) starts each in about
|
|
42
|
+
a third of the time: 0.5 ms rather than 1.6 ms on a 100-scene project.
|
|
43
|
+
- **The conformance corpus covers more, and every runtime is held to it**: the outline and beat sequence, the
|
|
44
|
+
audio resolver's joins, `listProperties`, what a checkpoint refuses while it is open, a save taken inside one,
|
|
45
|
+
and a block named under another scene.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- **Tags handed out are the caller's own.** `tagsForBeat`, `tagsForScene`, `tagsForBlock`, and a delivered
|
|
50
|
+
line's `tags` are copies, so a game that edits one changes nothing the engine says afterwards.
|
|
51
|
+
|
|
36
52
|
## [0.20.0] - 2026-10-06
|
|
37
53
|
|
|
38
54
|
### Added
|
package/dist/index.cjs
CHANGED
|
@@ -76,6 +76,18 @@ function buildTagIndex(bundle) {
|
|
|
76
76
|
// src/engine.ts
|
|
77
77
|
var import_model2 = require("@patterkit/model");
|
|
78
78
|
var astCache = /* @__PURE__ */ new WeakMap();
|
|
79
|
+
var tagIndexCache = /* @__PURE__ */ new WeakMap();
|
|
80
|
+
function tagIndexFor(bundle) {
|
|
81
|
+
let index = tagIndexCache.get(bundle);
|
|
82
|
+
if (!index) {
|
|
83
|
+
index = buildTagIndex(bundle);
|
|
84
|
+
tagIndexCache.set(bundle, index);
|
|
85
|
+
}
|
|
86
|
+
return index;
|
|
87
|
+
}
|
|
88
|
+
function tagsOf(host, id) {
|
|
89
|
+
return host.tagIndex.get(id)?.slice();
|
|
90
|
+
}
|
|
79
91
|
var OWNER = "Patter";
|
|
80
92
|
var esc = (id) => id.replace(/%/g, "%25").replace(/\//g, "%2F");
|
|
81
93
|
var OWNS_REGISTRY = /* @__PURE__ */ Symbol("ownsRegistry");
|
|
@@ -204,7 +216,7 @@ var Engine = class _Engine {
|
|
|
204
216
|
sceneGameIdToId: this.sceneGameIdToId,
|
|
205
217
|
blockGameIdToId: this.blockGameIdToId,
|
|
206
218
|
// same instances the engine resolves with
|
|
207
|
-
tagIndex:
|
|
219
|
+
tagIndex: tagIndexFor(bundle),
|
|
208
220
|
registry,
|
|
209
221
|
ownsRegistry,
|
|
210
222
|
patterBag,
|
|
@@ -463,18 +475,18 @@ var Engine = class _Engine {
|
|
|
463
475
|
* delivered step carries. Empty array for an unknown id or a beat with no tags anywhere up the chain.
|
|
464
476
|
*/
|
|
465
477
|
tagsForBeat(beatId) {
|
|
466
|
-
return this.host
|
|
478
|
+
return tagsOf(this.host, beatId) ?? [];
|
|
467
479
|
}
|
|
468
480
|
/** A scene's own tags (by internal id or gameId address). Empty when none / unknown. */
|
|
469
481
|
tagsForScene(sceneRef) {
|
|
470
482
|
const id = this.resolveSceneRef(sceneRef);
|
|
471
|
-
return (id != null ? this.host
|
|
483
|
+
return (id != null ? tagsOf(this.host, id) : void 0) ?? [];
|
|
472
484
|
}
|
|
473
485
|
/** A block's accumulated tags (scene + block), by scene + block ref (id or gameId). Empty when none / unknown. */
|
|
474
486
|
tagsForBlock(sceneRef, blockRef) {
|
|
475
487
|
const sceneId = this.resolveSceneRef(sceneRef);
|
|
476
488
|
const id = this.resolveBlockRef(sceneId, blockRef);
|
|
477
|
-
return (id != null ? this.host
|
|
489
|
+
return (id != null ? tagsOf(this.host, id) : void 0) ?? [];
|
|
478
490
|
}
|
|
479
491
|
/**
|
|
480
492
|
* A scene's own author gameData (by internal id or gameId address): the RAW sparse overrides, exactly
|
|
@@ -593,7 +605,7 @@ var Engine = class _Engine {
|
|
|
593
605
|
}
|
|
594
606
|
/** One beat's static data (source locale), the same shape a delivered step carries. */
|
|
595
607
|
beatInfo(beat) {
|
|
596
|
-
const tags = this.host
|
|
608
|
+
const tags = tagsOf(this.host, beat.id);
|
|
597
609
|
const info = { id: beat.id, kind: beat.kind };
|
|
598
610
|
if (beat.kind === "line") {
|
|
599
611
|
if (beat.character !== void 0) {
|
|
@@ -613,7 +625,7 @@ var Engine = class _Engine {
|
|
|
613
625
|
}
|
|
614
626
|
/** A `{ tags }` fragment for an id, present only when the id has accumulated tags (keeps output tidy). */
|
|
615
627
|
tagsField(id) {
|
|
616
|
-
const tags = this.host
|
|
628
|
+
const tags = tagsOf(this.host, id);
|
|
617
629
|
return tags && tags.length ? { tags } : {};
|
|
618
630
|
}
|
|
619
631
|
/** Retrieve an open flow by id (undefined if none / closed). */
|
|
@@ -750,8 +762,6 @@ var Engine = class _Engine {
|
|
|
750
762
|
this.host.registry.set(scope, name, value, { host: true });
|
|
751
763
|
if (this.host.journal && prev !== void 0) this.host.journal.undo.push(() => this.host.registry.set(scope, name, prev, { host: true }));
|
|
752
764
|
}
|
|
753
|
-
/** The shared `@patter` properties, for a live state inspector: each with its ref, type, current
|
|
754
|
-
* value, declared default (for reset), and enum options. Mirrors the Unity / Godot ports. */
|
|
755
765
|
/** The run's decisions, in order, each naming the flow it happened in. Empty unless the
|
|
756
766
|
* run was opened with `log: true`. A flow's own log stays flow-local; this is the only
|
|
757
767
|
* place a story spanning several flows reads as one sequence. */
|
|
@@ -783,6 +793,8 @@ var Engine = class _Engine {
|
|
|
783
793
|
getVisitCounts() {
|
|
784
794
|
return Object.fromEntries(this.host.sharedVisits);
|
|
785
795
|
}
|
|
796
|
+
/** The shared `@patter` properties, for a live state inspector: each with its ref, type, current
|
|
797
|
+
* value, declared default (for reset), and enum options. Every runtime has the same call. */
|
|
786
798
|
listProperties() {
|
|
787
799
|
return this.host.patterSharedDecls.map((d) => ({
|
|
788
800
|
name: d.name,
|
|
@@ -1770,7 +1782,7 @@ var Flow = class {
|
|
|
1770
1782
|
};
|
|
1771
1783
|
// -- Strings / beats ------------------------------------------------------
|
|
1772
1784
|
beatResult(beat) {
|
|
1773
|
-
const tags = this.host
|
|
1785
|
+
const tags = tagsOf(this.host, beat.id);
|
|
1774
1786
|
const withTags = tags && tags.length ? { tags } : {};
|
|
1775
1787
|
switch (beat.kind) {
|
|
1776
1788
|
case "gameEvent":
|
|
@@ -1837,7 +1849,7 @@ var Flow = class {
|
|
|
1837
1849
|
/** A replayed prompt as a step: the beat's id, gameData, and tags, and the text and speaker fields the
|
|
1838
1850
|
* choice showed. */
|
|
1839
1851
|
promptResult(beat, shown) {
|
|
1840
|
-
const tags = this.host
|
|
1852
|
+
const tags = tagsOf(this.host, beat.id);
|
|
1841
1853
|
const withTags = tags && tags.length ? { tags } : {};
|
|
1842
1854
|
if (shown.kind === "text") return { type: "text", id: beat.id, text: shown.text, gameData: beat.gameData, ...withTags };
|
|
1843
1855
|
return {
|