@spearwolf/shadow-objects 0.30.1 → 0.31.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/README.md +34 -10
- package/bundle.js +13 -13
- package/package.json +3 -3
- package/src/bundle.js +4 -4
- package/src/bundle.js.map +7 -1
- package/src/constants.js +53 -40
- package/src/constants.js.map +7 -1
- package/src/create-worker.bundle.js +6 -8
- package/src/create-worker.bundle.js.map +7 -1
- package/src/create-worker.js +5 -2
- package/src/create-worker.js.map +7 -1
- package/src/elements/ShaeElement.js +57 -54
- package/src/elements/ShaeElement.js.map +7 -1
- package/src/elements/ShaeEntElement.d.ts.map +1 -1
- package/src/elements/ShaeEntElement.js +320 -341
- package/src/elements/ShaeEntElement.js.map +7 -1
- package/src/elements/ShaePropElement.js +312 -320
- package/src/elements/ShaePropElement.js.map +7 -1
- package/src/elements/ShaeWorkerElement.js +234 -229
- package/src/elements/ShaeWorkerElement.js.map +7 -1
- package/src/elements/constants.js +37 -22
- package/src/elements/constants.js.map +7 -1
- package/src/elements/events.d.ts +1 -1
- package/src/elements/events.d.ts.map +1 -1
- package/src/elements/events.js +1 -2
- package/src/elements/events.js.map +7 -1
- package/src/elements.js +4 -4
- package/src/elements.js.map +7 -1
- package/src/in-the-dark/Entity.d.ts +3 -1
- package/src/in-the-dark/Entity.d.ts.map +1 -1
- package/src/in-the-dark/Entity.js +299 -275
- package/src/in-the-dark/Entity.js.map +7 -1
- package/src/in-the-dark/Kernel.d.ts +1 -1
- package/src/in-the-dark/Kernel.d.ts.map +1 -1
- package/src/in-the-dark/Kernel.js +556 -532
- package/src/in-the-dark/Kernel.js.map +7 -1
- package/src/in-the-dark/Registry.d.ts.map +1 -1
- package/src/in-the-dark/Registry.js +101 -104
- package/src/in-the-dark/Registry.js.map +7 -1
- package/src/in-the-dark/ShadowObject.d.ts.map +1 -1
- package/src/in-the-dark/ShadowObject.js +21 -23
- package/src/in-the-dark/ShadowObject.js.map +7 -1
- package/src/in-the-dark/SignalsPath.d.ts.map +1 -1
- package/src/in-the-dark/SignalsPath.js +139 -123
- package/src/in-the-dark/SignalsPath.js.map +7 -1
- package/src/in-the-dark/events.js +11 -9
- package/src/in-the-dark/events.js.map +7 -1
- package/src/in-the-dark/importModule.js +31 -29
- package/src/in-the-dark/importModule.js.map +7 -1
- package/src/index.d.ts +2 -2
- package/src/index.d.ts.map +1 -1
- package/src/index.js +14 -14
- package/src/index.js.map +7 -1
- package/src/shadow-objects.js +6 -6
- package/src/shadow-objects.js.map +7 -1
- package/src/shadow-objects.worker.js +3 -3
- package/src/shadow-objects.worker.js.map +7 -1
- package/src/shae-ent.js +3 -3
- package/src/shae-ent.js.map +7 -1
- package/src/shae-prop.js +3 -3
- package/src/shae-prop.js.map +7 -1
- package/src/shae-worker.js +3 -3
- package/src/shae-worker.js.map +7 -1
- package/src/types.d.ts +5 -4
- package/src/types.d.ts.map +1 -1
- package/src/types.js +1 -2
- package/src/types.js.map +7 -1
- package/src/utils/ConsoleLogger.js +179 -185
- package/src/utils/ConsoleLogger.js.map +7 -1
- package/src/utils/FrameLoop.js +41 -40
- package/src/utils/FrameLoop.js.map +7 -1
- package/src/utils/array-utils.js +22 -24
- package/src/utils/array-utils.js.map +7 -1
- package/src/utils/attr-utils.js +15 -11
- package/src/utils/attr-utils.js.map +7 -1
- package/src/utils/constants.js +5 -2
- package/src/utils/constants.js.map +7 -1
- package/src/utils/generateUUID.d.ts.map +1 -1
- package/src/utils/generateUUID.js +269 -32
- package/src/utils/generateUUID.js.map +7 -1
- package/src/utils/props-utils.js +34 -43
- package/src/utils/props-utils.js.map +7 -1
- package/src/utils/toMaybe.js +5 -2
- package/src/utils/toMaybe.js.map +7 -1
- package/src/utils/toNamespace.js +6 -3
- package/src/utils/toNamespace.js.map +7 -1
- package/src/utils/toUrlString.js +9 -6
- package/src/utils/toUrlString.js.map +7 -1
- package/src/utils/waitForMessageOfType.js +30 -32
- package/src/utils/waitForMessageOfType.js.map +7 -1
- package/src/view/ComponentChanges.d.ts +1 -1
- package/src/view/ComponentChanges.d.ts.map +1 -1
- package/src/view/ComponentChanges.js +249 -251
- package/src/view/ComponentChanges.js.map +7 -1
- package/src/view/ComponentContext.d.ts.map +1 -1
- package/src/view/ComponentContext.js +303 -331
- package/src/view/ComponentContext.js.map +7 -1
- package/src/view/ComponentMemory.d.ts +1 -0
- package/src/view/ComponentMemory.d.ts.map +1 -1
- package/src/view/ComponentMemory.js +73 -76
- package/src/view/ComponentMemory.js.map +7 -1
- package/src/view/IShadowObjectEnvProxy.js +1 -2
- package/src/view/IShadowObjectEnvProxy.js.map +7 -1
- package/src/view/LocalShadowObjectEnv.d.ts.map +1 -1
- package/src/view/LocalShadowObjectEnv.js +57 -52
- package/src/view/LocalShadowObjectEnv.js.map +7 -1
- package/src/view/RemoteWorkerEnv.js +134 -123
- package/src/view/RemoteWorkerEnv.js.map +7 -1
- package/src/view/ShadowEnv.d.ts.map +1 -1
- package/src/view/ShadowEnv.js +232 -228
- package/src/view/ShadowEnv.js.map +7 -1
- package/src/view/ViewComponent.d.ts +9 -0
- package/src/view/ViewComponent.d.ts.map +1 -1
- package/src/view/ViewComponent.js +142 -130
- package/src/view/ViewComponent.js.map +7 -1
- package/src/view/cloneChangeTrail.js +13 -11
- package/src/view/cloneChangeTrail.js.map +7 -1
- package/src/worker/MessageRouter.d.ts.map +1 -1
- package/src/worker/MessageRouter.js +78 -67
- package/src/worker/MessageRouter.js.map +7 -1
- package/src/worker/WorkerRuntime.js +22 -21
- package/src/worker/WorkerRuntime.js.map +7 -1
- package/tsconfig.lib.tsbuildinfo +0 -1
|
@@ -1,568 +1,592 @@
|
|
|
1
|
-
import { emit, eventize, off, on, once, Priority } from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { emit, eventize, off, on, once, Priority } from "@spearwolf/eventize";
|
|
2
|
+
import {
|
|
3
|
+
batch,
|
|
4
|
+
createEffect,
|
|
5
|
+
createMemo,
|
|
6
|
+
createSignal,
|
|
7
|
+
destroySignal,
|
|
8
|
+
isSignal,
|
|
9
|
+
link
|
|
10
|
+
} from "@spearwolf/signalize";
|
|
11
|
+
import { ComponentChangeType, MessageToView } from "../constants.js";
|
|
12
|
+
import { ConsoleLogger } from "../utils/ConsoleLogger.js";
|
|
13
|
+
import { toMaybe } from "../utils/toMaybe.js";
|
|
14
|
+
import { Entity } from "./Entity.js";
|
|
15
|
+
import { onCreate, onDestroy, onParentChanged, onViewEvent } from "./events.js";
|
|
16
|
+
import { Registry } from "./Registry.js";
|
|
17
|
+
import { SignalsPath } from "./SignalsPath.js";
|
|
18
|
+
var ShadowObjectAction = /* @__PURE__ */ ((ShadowObjectAction2) => {
|
|
19
|
+
ShadowObjectAction2[ShadowObjectAction2["CreateAndDestroy"] = 0] = "CreateAndDestroy";
|
|
20
|
+
ShadowObjectAction2[ShadowObjectAction2["JustCreate"] = 1] = "JustCreate";
|
|
21
|
+
ShadowObjectAction2[ShadowObjectAction2["DestroyOnly"] = 2] = "DestroyOnly";
|
|
22
|
+
return ShadowObjectAction2;
|
|
23
|
+
})(ShadowObjectAction || {});
|
|
16
24
|
const getDisplayName = (construct) => construct.displayName || construct.name;
|
|
17
25
|
let provideContextOptionsDeprecatedShown = false;
|
|
18
26
|
let provideGlobalContextOptionsDeprecatedShown = false;
|
|
19
27
|
let useContextOptionsDeprecatedShown = false;
|
|
20
28
|
let useParentContextOptionsDeprecatedShown = false;
|
|
21
29
|
let usePropertyOptionsDeprecatedShown = false;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
eventize(this);
|
|
43
|
-
this.registry = Registry.get(registry);
|
|
30
|
+
class Kernel {
|
|
31
|
+
constructor(registry) {
|
|
32
|
+
this.logger = new ConsoleLogger("Kernel");
|
|
33
|
+
this.#entities = /* @__PURE__ */ new Map();
|
|
34
|
+
this.#rootEntities = /* @__PURE__ */ new Set();
|
|
35
|
+
this.#allEntitiesNeedUpdate = true;
|
|
36
|
+
this.#rootContexts = /* @__PURE__ */ new Map();
|
|
37
|
+
eventize(this);
|
|
38
|
+
this.registry = Registry.get(registry);
|
|
39
|
+
}
|
|
40
|
+
#entities;
|
|
41
|
+
#rootEntities;
|
|
42
|
+
#allEntities;
|
|
43
|
+
#allEntitiesReversed;
|
|
44
|
+
#allEntitiesNeedUpdate;
|
|
45
|
+
#rootContexts;
|
|
46
|
+
getEntity(uuid) {
|
|
47
|
+
const entity = this.#entities.get(uuid)?.entity;
|
|
48
|
+
if (!entity) {
|
|
49
|
+
throw new Error(`entity with uuid "${uuid}" not found!`);
|
|
44
50
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
return entity;
|
|
52
|
+
}
|
|
53
|
+
hasEntity(uuid) {
|
|
54
|
+
return this.#entities.has(uuid);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @returns all entities in breadth-first order
|
|
58
|
+
*/
|
|
59
|
+
traverseLevelOrderBFS(reverse = false) {
|
|
60
|
+
if (this.#allEntitiesNeedUpdate) {
|
|
61
|
+
const lvl = /* @__PURE__ */ new Map();
|
|
62
|
+
const traverse = (uuid, depth) => {
|
|
63
|
+
const e = this.getEntity(uuid);
|
|
64
|
+
if (lvl.has(depth)) {
|
|
65
|
+
lvl.get(depth).push(e);
|
|
66
|
+
} else {
|
|
67
|
+
lvl.set(depth, [e]);
|
|
49
68
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
hasEntity(uuid) {
|
|
53
|
-
return this.#entities.has(uuid);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* @returns all entities in breadth-first order
|
|
57
|
-
*/
|
|
58
|
-
traverseLevelOrderBFS(reverse = false) {
|
|
59
|
-
if (this.#allEntitiesNeedUpdate) {
|
|
60
|
-
const lvl = new Map();
|
|
61
|
-
const traverse = (uuid, depth) => {
|
|
62
|
-
const e = this.getEntity(uuid);
|
|
63
|
-
if (lvl.has(depth)) {
|
|
64
|
-
lvl.get(depth).push(e);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
lvl.set(depth, [e]);
|
|
68
|
-
}
|
|
69
|
-
for (const child of e.children) {
|
|
70
|
-
traverse(child.uuid, depth + 1);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
this.#rootEntities.forEach((uuid) => {
|
|
74
|
-
traverse(uuid, 0);
|
|
75
|
-
});
|
|
76
|
-
this.#allEntities = Array.from(lvl.entries())
|
|
77
|
-
.sort((a, b) => a[0] - b[0])
|
|
78
|
-
.flatMap(([, entities]) => entities);
|
|
79
|
-
this.#allEntitiesReversed = this.#allEntities.slice().reverse();
|
|
80
|
-
this.#allEntitiesNeedUpdate = false;
|
|
69
|
+
for (const child of e.children) {
|
|
70
|
+
traverse(child.uuid, depth + 1);
|
|
81
71
|
}
|
|
82
|
-
|
|
72
|
+
};
|
|
73
|
+
this.#rootEntities.forEach((uuid) => {
|
|
74
|
+
traverse(uuid, 0);
|
|
75
|
+
});
|
|
76
|
+
this.#allEntities = Array.from(lvl.entries()).sort((a, b) => a[0] - b[0]).flatMap(([, entities]) => entities);
|
|
77
|
+
this.#allEntitiesReversed = this.#allEntities.slice().reverse();
|
|
78
|
+
this.#allEntitiesNeedUpdate = false;
|
|
83
79
|
}
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
return reverse ? this.#allEntitiesReversed : this.#allEntities;
|
|
81
|
+
}
|
|
82
|
+
getEntityGraph() {
|
|
83
|
+
return Array.from(this.#rootEntities).map((uuid) => this.getEntityGraphNode(uuid));
|
|
84
|
+
}
|
|
85
|
+
getEntityGraphNode(uuid) {
|
|
86
|
+
if (!this.#entities.has(uuid)) return void 0;
|
|
87
|
+
const { token, entity } = this.#entities.get(uuid);
|
|
88
|
+
return {
|
|
89
|
+
token,
|
|
90
|
+
entity,
|
|
91
|
+
props: Object.fromEntries(entity.propEntries()),
|
|
92
|
+
children: entity.children.map((child) => this.getEntityGraphNode(child.uuid))
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
upgradeEntities() {
|
|
96
|
+
const entityConstructors = /* @__PURE__ */ new Map();
|
|
97
|
+
for (const entity of this.traverseLevelOrderBFS(true)) {
|
|
98
|
+
entityConstructors.set(entity.uuid, this.updateShadowObjects(entity.uuid, 2 /* DestroyOnly */));
|
|
86
99
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return undefined;
|
|
90
|
-
const { token, entity } = this.#entities.get(uuid);
|
|
91
|
-
return {
|
|
92
|
-
token,
|
|
93
|
-
entity,
|
|
94
|
-
props: Object.fromEntries(entity.propEntries()),
|
|
95
|
-
children: entity.children.map((child) => this.getEntityGraphNode(child.uuid)),
|
|
96
|
-
};
|
|
100
|
+
for (const entity of this.traverseLevelOrderBFS(false)) {
|
|
101
|
+
this.updateShadowObjects(entity.uuid, 1 /* JustCreate */, entityConstructors.get(entity.uuid));
|
|
97
102
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
for (const entity of this.traverseLevelOrderBFS(false)) {
|
|
104
|
-
this.updateShadowObjects(entity.uuid, ShadowObjectAction.JustCreate, entityConstructors.get(entity.uuid));
|
|
105
|
-
}
|
|
106
|
-
entityConstructors.clear();
|
|
107
|
-
}
|
|
108
|
-
run(event) {
|
|
109
|
-
if (this.logger.isDebug) {
|
|
110
|
-
this.logger.debug('sync', event);
|
|
111
|
-
}
|
|
112
|
-
batch(() => {
|
|
113
|
-
for (const entry of event.changeTrail) {
|
|
114
|
-
this.parse(entry);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
103
|
+
entityConstructors.clear();
|
|
104
|
+
}
|
|
105
|
+
run(event) {
|
|
106
|
+
if (this.logger.isDebug) {
|
|
107
|
+
this.logger.debug("sync", event);
|
|
117
108
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (properties) {
|
|
159
|
-
e.setProperties(properties);
|
|
160
|
-
}
|
|
161
|
-
this.createShadowObjects(uuid);
|
|
162
|
-
}
|
|
163
|
-
destroyEntity(uuid) {
|
|
164
|
-
if (!this.#entities.has(uuid))
|
|
165
|
-
return;
|
|
166
|
-
const { entity, usedConstructors } = this.#entities.get(uuid);
|
|
167
|
-
entity.removeFromParent();
|
|
168
|
-
emit(entity, onDestroy, entity);
|
|
169
|
-
usedConstructors.clear();
|
|
170
|
-
this.#entities.delete(entity.uuid);
|
|
171
|
-
this.#rootEntities.delete(entity.uuid);
|
|
109
|
+
batch(() => {
|
|
110
|
+
for (const entry of event.changeTrail) {
|
|
111
|
+
this.parse(entry);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
parse(entry) {
|
|
116
|
+
switch (entry.type) {
|
|
117
|
+
case ComponentChangeType.CreateEntities:
|
|
118
|
+
this.createEntity(
|
|
119
|
+
entry.uuid,
|
|
120
|
+
entry.token,
|
|
121
|
+
entry.parentUuid,
|
|
122
|
+
entry.order,
|
|
123
|
+
entry.properties,
|
|
124
|
+
entry.autoDestructionOnParentRemoval
|
|
125
|
+
);
|
|
126
|
+
this.#allEntitiesNeedUpdate = true;
|
|
127
|
+
break;
|
|
128
|
+
case ComponentChangeType.DestroyEntities:
|
|
129
|
+
this.destroyEntity(entry.uuid);
|
|
130
|
+
this.#allEntitiesNeedUpdate = true;
|
|
131
|
+
break;
|
|
132
|
+
case ComponentChangeType.SetParent:
|
|
133
|
+
this.setParent(entry.uuid, entry.parentUuid, entry.order);
|
|
134
|
+
this.#allEntitiesNeedUpdate = true;
|
|
135
|
+
break;
|
|
136
|
+
case ComponentChangeType.UpdateOrder:
|
|
137
|
+
this.updateOrder(entry.uuid, entry.order);
|
|
138
|
+
this.#allEntitiesNeedUpdate = true;
|
|
139
|
+
break;
|
|
140
|
+
case ComponentChangeType.ChangeProperties:
|
|
141
|
+
this.changeProperties(entry.uuid, entry.properties);
|
|
142
|
+
break;
|
|
143
|
+
case ComponentChangeType.ChangeToken:
|
|
144
|
+
this.changeToken(entry.uuid, entry.token);
|
|
145
|
+
break;
|
|
146
|
+
case ComponentChangeType.SendEvents:
|
|
147
|
+
this.dispatchEventsToEntity(entry.uuid, entry.events);
|
|
148
|
+
break;
|
|
172
149
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.#rootEntities.delete(uuid);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
this.#rootEntities.add(uuid);
|
|
185
|
-
}
|
|
186
|
-
e.reSubscribeToParentContexts();
|
|
187
|
-
queueMicrotask(() => {
|
|
188
|
-
if (this.logger.isDebug) {
|
|
189
|
-
this.logger.debug('entity.onParentChanged', { uuid, parentUuid, order, entity: e });
|
|
190
|
-
}
|
|
191
|
-
emit(e, onParentChanged, e);
|
|
192
|
-
});
|
|
150
|
+
}
|
|
151
|
+
createEntity(uuid, token, parentUuid, order = 0, properties, autoDestructionOnParentRemoval = false) {
|
|
152
|
+
const e = new Entity(this, uuid);
|
|
153
|
+
e.order = order;
|
|
154
|
+
const entry = { token, entity: e, usedConstructors: /* @__PURE__ */ new Map() };
|
|
155
|
+
this.#entities.set(uuid, entry);
|
|
156
|
+
if (parentUuid) {
|
|
157
|
+
e.parentUuid = parentUuid;
|
|
193
158
|
}
|
|
194
|
-
|
|
195
|
-
|
|
159
|
+
e.autoDestructionOnParentRemoval = autoDestructionOnParentRemoval;
|
|
160
|
+
if (!e.hasParent) {
|
|
161
|
+
this.#rootEntities.add(uuid);
|
|
196
162
|
}
|
|
197
|
-
|
|
198
|
-
|
|
163
|
+
if (properties) {
|
|
164
|
+
e.setProperties(properties);
|
|
199
165
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
166
|
+
this.createShadowObjects(uuid);
|
|
167
|
+
}
|
|
168
|
+
destroyEntity(uuid) {
|
|
169
|
+
if (!this.#entities.has(uuid)) return;
|
|
170
|
+
const { entity, usedConstructors } = this.#entities.get(uuid);
|
|
171
|
+
const childrenSnapshot = [...entity.children];
|
|
172
|
+
for (const child of childrenSnapshot) {
|
|
173
|
+
if (child.autoDestructionOnParentRemoval) {
|
|
174
|
+
this.destroyEntity(child.uuid);
|
|
175
|
+
} else {
|
|
176
|
+
child.removeFromParent();
|
|
177
|
+
this.#rootEntities.add(child.uuid);
|
|
178
|
+
}
|
|
203
179
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
180
|
+
entity.removeFromParent();
|
|
181
|
+
emit(entity, onDestroy, entity);
|
|
182
|
+
usedConstructors.clear();
|
|
183
|
+
this.#entities.delete(entity.uuid);
|
|
184
|
+
this.#rootEntities.delete(entity.uuid);
|
|
185
|
+
this.#allEntitiesNeedUpdate = true;
|
|
186
|
+
}
|
|
187
|
+
setParent(uuid, parentUuid, order = 0) {
|
|
188
|
+
const e = this.getEntity(uuid);
|
|
189
|
+
if (e.parentUuid === parentUuid && e.order === order) return;
|
|
190
|
+
if (parentUuid && !this.#entities.has(parentUuid)) {
|
|
191
|
+
throw new Error(`entity with uuid "${parentUuid}" not found!`);
|
|
212
192
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
193
|
+
e.removeFromParent();
|
|
194
|
+
e.order = order;
|
|
195
|
+
e.parentUuid = parentUuid;
|
|
196
|
+
if (e.hasParent) {
|
|
197
|
+
this.#rootEntities.delete(uuid);
|
|
198
|
+
} else {
|
|
199
|
+
this.#rootEntities.add(uuid);
|
|
217
200
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
201
|
+
e.reSubscribeToParentContexts();
|
|
202
|
+
queueMicrotask(() => {
|
|
203
|
+
if (this.logger.isDebug) {
|
|
204
|
+
this.logger.debug("entity.onParentChanged", { uuid, parentUuid, order, entity: e });
|
|
205
|
+
}
|
|
206
|
+
emit(e, onParentChanged, e);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
updateOrder(uuid, order) {
|
|
210
|
+
this.getEntity(uuid).order = order;
|
|
211
|
+
}
|
|
212
|
+
dispatchEventsToEntity(uuid, events) {
|
|
213
|
+
this.getEntity(uuid)?.dispatchViewEvents(events);
|
|
214
|
+
}
|
|
215
|
+
changeProperties(uuid, properties) {
|
|
216
|
+
this.getEntity(uuid).setProperties(properties);
|
|
217
|
+
this.updateShadowObjects(uuid);
|
|
218
|
+
}
|
|
219
|
+
changeToken(uuid, token) {
|
|
220
|
+
if (!this.#entities.has(uuid)) return;
|
|
221
|
+
const entry = this.#entities.get(uuid);
|
|
222
|
+
if (entry.token === token) return;
|
|
223
|
+
entry.token = token;
|
|
224
|
+
this.updateShadowObjects(uuid);
|
|
225
|
+
}
|
|
226
|
+
dispatchMessageToView(message) {
|
|
227
|
+
queueMicrotask(() => {
|
|
228
|
+
emit(this, MessageToView, message);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Create or destroy the shadow-objects of an entity using the registered constructors.
|
|
233
|
+
* After a token change or registry changes, an entity may be given different shadow-objects.
|
|
234
|
+
*/
|
|
235
|
+
updateShadowObjects(uuid, action = 0 /* CreateAndDestroy */, nextConstructors) {
|
|
236
|
+
const entry = this.#entities.get(uuid);
|
|
237
|
+
nextConstructors ??= new Set(this.registry.findConstructors(entry.token, entry.entity.truthyProps()));
|
|
238
|
+
const shouldDestroy = action === 0 /* CreateAndDestroy */ || action === 2 /* DestroyOnly */;
|
|
239
|
+
const shouldCreate = action === 0 /* CreateAndDestroy */ || action === 1 /* JustCreate */;
|
|
240
|
+
if (shouldDestroy) {
|
|
241
|
+
for (const [construct, shadowObjects] of entry.usedConstructors) {
|
|
242
|
+
if (!nextConstructors.has(construct)) {
|
|
243
|
+
entry.usedConstructors.delete(construct);
|
|
244
|
+
for (const obj of shadowObjects) {
|
|
245
|
+
this.destroyShadowObject(obj, entry.entity);
|
|
246
|
+
}
|
|
238
247
|
}
|
|
239
|
-
|
|
240
|
-
//
|
|
241
|
-
if (shouldCreate) {
|
|
242
|
-
for (const construct of nextConstructors) {
|
|
243
|
-
if (!entry.usedConstructors.has(construct)) {
|
|
244
|
-
this.constructShadowObject(construct, entry);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return nextConstructors;
|
|
248
|
+
}
|
|
249
249
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const contextParentReaders = new Map();
|
|
255
|
-
const contextProviders = new Map();
|
|
256
|
-
const contextRootProviders = new Map();
|
|
257
|
-
const propertyReaders = new Map();
|
|
258
|
-
const getUseProperty = (name, options) => {
|
|
259
|
-
if (!usePropertyOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
260
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "useProperty()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
261
|
-
usePropertyOptionsDeprecatedShown = true;
|
|
262
|
-
}
|
|
263
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
264
|
-
let propReader = propertyReaders.get(name);
|
|
265
|
-
if (propReader === undefined) {
|
|
266
|
-
propReader = createSignal(undefined, opts).get;
|
|
267
|
-
propertyReaders.set(name, propReader);
|
|
268
|
-
const con = link(entry.entity.getPropertyReader(name), propReader);
|
|
269
|
-
unsubscribeSecondary.add(con.destroy.bind(con));
|
|
270
|
-
}
|
|
271
|
-
return propReader;
|
|
272
|
-
};
|
|
273
|
-
const shadowObject = eventize(new construct({
|
|
274
|
-
entity: entry.entity,
|
|
275
|
-
provideContext(name, sourceOrInitialValue, options) {
|
|
276
|
-
if (!provideContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
277
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "provideContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
278
|
-
provideContextOptionsDeprecatedShown = true;
|
|
279
|
-
}
|
|
280
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
281
|
-
let ctxProvider = contextProviders.get(name);
|
|
282
|
-
if (ctxProvider == null) {
|
|
283
|
-
const isSig = isSignal(sourceOrInitialValue);
|
|
284
|
-
const initialValue = isSig ? undefined : toMaybe(sourceOrInitialValue);
|
|
285
|
-
ctxProvider = createSignal(initialValue, opts?.compare ? { compare: opts.compare } : undefined);
|
|
286
|
-
if (isSig) {
|
|
287
|
-
const ln = link(sourceOrInitialValue, ctxProvider);
|
|
288
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
289
|
-
}
|
|
290
|
-
const ln = link(ctxProvider, entry.entity.provideContext(name));
|
|
291
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
292
|
-
contextProviders.set(name, ctxProvider);
|
|
293
|
-
}
|
|
294
|
-
if (ctxProvider != null && (opts?.clearOnDestroy ?? true)) {
|
|
295
|
-
unsubscribeSecondary.add(() => {
|
|
296
|
-
ctxProvider.set(undefined);
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
return ctxProvider;
|
|
300
|
-
},
|
|
301
|
-
provideGlobalContext(name, sourceOrInitialValue, options) {
|
|
302
|
-
if (!provideGlobalContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
303
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "provideGlobalContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
304
|
-
provideGlobalContextOptionsDeprecatedShown = true;
|
|
305
|
-
}
|
|
306
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
307
|
-
let ctxProvider = contextRootProviders.get(name);
|
|
308
|
-
if (ctxProvider == null) {
|
|
309
|
-
const isSig = isSignal(sourceOrInitialValue);
|
|
310
|
-
const initialValue = isSig ? undefined : toMaybe(sourceOrInitialValue);
|
|
311
|
-
ctxProvider = createSignal(initialValue, opts?.compare ? { compare: opts.compare } : undefined);
|
|
312
|
-
if (isSig) {
|
|
313
|
-
const ln = link(sourceOrInitialValue, ctxProvider);
|
|
314
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
315
|
-
}
|
|
316
|
-
const ln = link(ctxProvider, entry.entity.provideGlobalContext(name));
|
|
317
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
318
|
-
contextRootProviders.set(name, ctxProvider);
|
|
319
|
-
}
|
|
320
|
-
if (ctxProvider != null && (opts?.clearOnDestroy ?? true)) {
|
|
321
|
-
unsubscribeSecondary.add(() => {
|
|
322
|
-
ctxProvider.set(undefined);
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
return ctxProvider;
|
|
326
|
-
},
|
|
327
|
-
useContext(name, options) {
|
|
328
|
-
if (!useContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
329
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "useContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
330
|
-
useContextOptionsDeprecatedShown = true;
|
|
331
|
-
}
|
|
332
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
333
|
-
let ctxReader = contextReaders.get(name);
|
|
334
|
-
if (ctxReader === undefined) {
|
|
335
|
-
ctxReader = createSignal(undefined, opts).get;
|
|
336
|
-
contextReaders.set(name, ctxReader);
|
|
337
|
-
const ln = link(entry.entity.useContext(name), ctxReader);
|
|
338
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
339
|
-
}
|
|
340
|
-
return ctxReader;
|
|
341
|
-
},
|
|
342
|
-
useParentContext(name, options) {
|
|
343
|
-
if (!useParentContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
344
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "useParentContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
345
|
-
useParentContextOptionsDeprecatedShown = true;
|
|
346
|
-
}
|
|
347
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
348
|
-
let ctxReader = contextParentReaders.get(name);
|
|
349
|
-
if (ctxReader === undefined) {
|
|
350
|
-
ctxReader = createSignal(undefined, opts).get;
|
|
351
|
-
contextParentReaders.set(name, ctxReader);
|
|
352
|
-
const ln = link(entry.entity.useParentContext(name), ctxReader);
|
|
353
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
354
|
-
}
|
|
355
|
-
return ctxReader;
|
|
356
|
-
},
|
|
357
|
-
dispatchMessageToView(type, data, transferables, traverseChildren = false) {
|
|
358
|
-
entry.entity.dispatchMessageToView(type, data, transferables, traverseChildren);
|
|
359
|
-
},
|
|
360
|
-
useProperty: getUseProperty,
|
|
361
|
-
useProperties(props) {
|
|
362
|
-
const result = {};
|
|
363
|
-
for (const key in props) {
|
|
364
|
-
if (Object.hasOwn(props, key)) {
|
|
365
|
-
result[key] = getUseProperty(props[key]);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return result;
|
|
369
|
-
},
|
|
370
|
-
createResource(factory, cleanup) {
|
|
371
|
-
const resourceSignal = createSignal();
|
|
372
|
-
const effect = createEffect(() => {
|
|
373
|
-
const resource = toMaybe(factory());
|
|
374
|
-
resourceSignal.set(resource);
|
|
375
|
-
if (resource !== undefined && cleanup) {
|
|
376
|
-
return () => {
|
|
377
|
-
cleanup(resource);
|
|
378
|
-
resourceSignal.set(undefined);
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
return () => {
|
|
382
|
-
resourceSignal.set(undefined);
|
|
383
|
-
};
|
|
384
|
-
});
|
|
385
|
-
unsubscribeSecondary.add(() => {
|
|
386
|
-
effect.destroy();
|
|
387
|
-
resourceSignal.set(undefined);
|
|
388
|
-
destroySignal(resourceSignal);
|
|
389
|
-
});
|
|
390
|
-
return resourceSignal;
|
|
391
|
-
},
|
|
392
|
-
createEffect(...args) {
|
|
393
|
-
const effect = createEffect(...args);
|
|
394
|
-
unsubscribeSecondary.add(effect.destroy);
|
|
395
|
-
return effect;
|
|
396
|
-
},
|
|
397
|
-
createSignal(...args) {
|
|
398
|
-
const sig = createSignal(...args);
|
|
399
|
-
unsubscribeSecondary.add(() => {
|
|
400
|
-
destroySignal(sig);
|
|
401
|
-
});
|
|
402
|
-
return sig;
|
|
403
|
-
},
|
|
404
|
-
createMemo(...args) {
|
|
405
|
-
const sig = createMemo(...args);
|
|
406
|
-
unsubscribeSecondary.add(() => {
|
|
407
|
-
destroySignal(sig);
|
|
408
|
-
});
|
|
409
|
-
return sig;
|
|
410
|
-
},
|
|
411
|
-
on(...args) {
|
|
412
|
-
const [firstArg] = args;
|
|
413
|
-
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
|
|
414
|
-
// @ts-ignore
|
|
415
|
-
const unsub = on(entry.entity, ...args);
|
|
416
|
-
unsubscribeSecondary.add(unsub);
|
|
417
|
-
return unsub;
|
|
418
|
-
}
|
|
419
|
-
// @ts-ignore
|
|
420
|
-
const unsub = on(...args);
|
|
421
|
-
unsubscribeSecondary.add(unsub);
|
|
422
|
-
// return unsub;
|
|
423
|
-
return Object.assign(() => {
|
|
424
|
-
unsubscribeSecondary.delete(unsub);
|
|
425
|
-
unsub();
|
|
426
|
-
}, unsub);
|
|
427
|
-
},
|
|
428
|
-
once(...args) {
|
|
429
|
-
const [firstArg] = args;
|
|
430
|
-
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
|
|
431
|
-
// @ts-ignore
|
|
432
|
-
const unsub = once(entry.entity, ...args);
|
|
433
|
-
unsubscribeSecondary.add(unsub);
|
|
434
|
-
return unsub;
|
|
435
|
-
}
|
|
436
|
-
// @ts-ignore
|
|
437
|
-
const unsub = once(...args);
|
|
438
|
-
unsubscribeSecondary.add(unsub);
|
|
439
|
-
// return unsub;
|
|
440
|
-
return Object.assign(() => {
|
|
441
|
-
unsubscribeSecondary.delete(unsub);
|
|
442
|
-
unsub();
|
|
443
|
-
}, unsub);
|
|
444
|
-
},
|
|
445
|
-
emit(...args) {
|
|
446
|
-
const [firstArg] = args;
|
|
447
|
-
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
|
|
448
|
-
// @ts-ignore
|
|
449
|
-
emit(entry.entity, ...args);
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
// @ts-ignore
|
|
453
|
-
emit(...args);
|
|
454
|
-
}
|
|
455
|
-
},
|
|
456
|
-
onViewEvent(callback) {
|
|
457
|
-
const unsub = on(entry.entity, onViewEvent, (type, data) => {
|
|
458
|
-
callback(type, data);
|
|
459
|
-
});
|
|
460
|
-
unsubscribeSecondary.add(unsub);
|
|
461
|
-
},
|
|
462
|
-
onDestroy(callback) {
|
|
463
|
-
unsubscribePrimary.add(callback);
|
|
464
|
-
},
|
|
465
|
-
}));
|
|
466
|
-
if (this.logger.isInfo) {
|
|
467
|
-
this.logger.info('create shadow-object', getDisplayName(construct), { shadowObject, entity: entry.entity });
|
|
250
|
+
if (shouldCreate) {
|
|
251
|
+
for (const construct of nextConstructors) {
|
|
252
|
+
if (!entry.usedConstructors.has(construct)) {
|
|
253
|
+
this.constructShadowObject(construct, entry);
|
|
468
254
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return nextConstructors;
|
|
258
|
+
}
|
|
259
|
+
constructShadowObject(construct, entry) {
|
|
260
|
+
const unsubscribePrimary = /* @__PURE__ */ new Set();
|
|
261
|
+
const unsubscribeSecondary = /* @__PURE__ */ new Set();
|
|
262
|
+
const contextReaders = /* @__PURE__ */ new Map();
|
|
263
|
+
const contextReaderCompares = /* @__PURE__ */ new Map();
|
|
264
|
+
const contextParentReaders = /* @__PURE__ */ new Map();
|
|
265
|
+
const contextParentReaderCompares = /* @__PURE__ */ new Map();
|
|
266
|
+
const contextProviders = /* @__PURE__ */ new Map();
|
|
267
|
+
const contextRootProviders = /* @__PURE__ */ new Map();
|
|
268
|
+
const propertyReaders = /* @__PURE__ */ new Map();
|
|
269
|
+
const propertyCompares = /* @__PURE__ */ new Map();
|
|
270
|
+
const getUseProperty = (name, options) => {
|
|
271
|
+
if (!usePropertyOptionsDeprecatedShown && options != null && typeof options === "function") {
|
|
272
|
+
console.warn(
|
|
273
|
+
'[shadow-objects] Deprecation Warning: The "isEqual" option of "useProperty()" is now passed as {compare} argument. Please update your code accordingly.'
|
|
274
|
+
);
|
|
275
|
+
usePropertyOptionsDeprecatedShown = true;
|
|
276
|
+
}
|
|
277
|
+
const opts = typeof options === "function" ? { compare: options } : options;
|
|
278
|
+
let propReader = propertyReaders.get(name);
|
|
279
|
+
if (propReader === void 0) {
|
|
280
|
+
propReader = createSignal(void 0, opts).get;
|
|
281
|
+
propertyReaders.set(name, propReader);
|
|
282
|
+
propertyCompares.set(name, opts?.compare);
|
|
283
|
+
const con = link(entry.entity.getPropertyReader(name), propReader);
|
|
284
|
+
unsubscribeSecondary.add(con.destroy.bind(con));
|
|
285
|
+
} else if (opts?.compare != null && propertyCompares.get(name) !== opts.compare) {
|
|
286
|
+
console.warn(
|
|
287
|
+
`[shadow-objects] useProperty("${name}"): the cached signal already exists with a different (or no) {compare} function \u2014 the new options are ignored. Pass options only on the first call per property.`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return propReader;
|
|
291
|
+
};
|
|
292
|
+
const shadowObject = eventize(
|
|
293
|
+
new construct({
|
|
294
|
+
entity: entry.entity,
|
|
295
|
+
provideContext(name, sourceOrInitialValue, options) {
|
|
296
|
+
if (!provideContextOptionsDeprecatedShown && options != null && typeof options === "function") {
|
|
297
|
+
console.warn(
|
|
298
|
+
'[shadow-objects] Deprecation Warning: The "isEqual" option of "provideContext()" is now passed as {compare} argument. Please update your code accordingly.'
|
|
299
|
+
);
|
|
300
|
+
provideContextOptionsDeprecatedShown = true;
|
|
301
|
+
}
|
|
302
|
+
const opts = typeof options === "function" ? { compare: options } : options;
|
|
303
|
+
let ctxProvider = contextProviders.get(name);
|
|
304
|
+
if (ctxProvider == null) {
|
|
305
|
+
const isSig = isSignal(sourceOrInitialValue);
|
|
306
|
+
const initialValue = isSig ? void 0 : toMaybe(sourceOrInitialValue);
|
|
307
|
+
ctxProvider = createSignal(initialValue, opts?.compare ? { compare: opts.compare } : void 0);
|
|
308
|
+
if (isSig) {
|
|
309
|
+
const ln2 = link(sourceOrInitialValue, ctxProvider);
|
|
310
|
+
unsubscribeSecondary.add(ln2.destroy.bind(ln2));
|
|
487
311
|
}
|
|
488
|
-
|
|
489
|
-
|
|
312
|
+
const ln = link(ctxProvider, entry.entity.provideContext(name));
|
|
313
|
+
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
314
|
+
contextProviders.set(name, ctxProvider);
|
|
315
|
+
}
|
|
316
|
+
if (ctxProvider != null && (opts?.clearOnDestroy ?? true)) {
|
|
317
|
+
unsubscribeSecondary.add(() => {
|
|
318
|
+
ctxProvider.set(void 0);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
return ctxProvider;
|
|
322
|
+
},
|
|
323
|
+
provideGlobalContext(name, sourceOrInitialValue, options) {
|
|
324
|
+
if (!provideGlobalContextOptionsDeprecatedShown && options != null && typeof options === "function") {
|
|
325
|
+
console.warn(
|
|
326
|
+
'[shadow-objects] Deprecation Warning: The "isEqual" option of "provideGlobalContext()" is now passed as {compare} argument. Please update your code accordingly.'
|
|
327
|
+
);
|
|
328
|
+
provideGlobalContextOptionsDeprecatedShown = true;
|
|
329
|
+
}
|
|
330
|
+
const opts = typeof options === "function" ? { compare: options } : options;
|
|
331
|
+
let ctxProvider = contextRootProviders.get(name);
|
|
332
|
+
if (ctxProvider == null) {
|
|
333
|
+
const isSig = isSignal(sourceOrInitialValue);
|
|
334
|
+
const initialValue = isSig ? void 0 : toMaybe(sourceOrInitialValue);
|
|
335
|
+
ctxProvider = createSignal(initialValue, opts?.compare ? { compare: opts.compare } : void 0);
|
|
336
|
+
if (isSig) {
|
|
337
|
+
const ln2 = link(sourceOrInitialValue, ctxProvider);
|
|
338
|
+
unsubscribeSecondary.add(ln2.destroy.bind(ln2));
|
|
490
339
|
}
|
|
491
|
-
|
|
492
|
-
|
|
340
|
+
const ln = link(ctxProvider, entry.entity.provideGlobalContext(name));
|
|
341
|
+
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
342
|
+
contextRootProviders.set(name, ctxProvider);
|
|
343
|
+
}
|
|
344
|
+
if (ctxProvider != null && (opts?.clearOnDestroy ?? true)) {
|
|
345
|
+
unsubscribeSecondary.add(() => {
|
|
346
|
+
ctxProvider.set(void 0);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
return ctxProvider;
|
|
350
|
+
},
|
|
351
|
+
useContext(name, options) {
|
|
352
|
+
if (!useContextOptionsDeprecatedShown && options != null && typeof options === "function") {
|
|
353
|
+
console.warn(
|
|
354
|
+
'[shadow-objects] Deprecation Warning: The "isEqual" option of "useContext()" is now passed as {compare} argument. Please update your code accordingly.'
|
|
355
|
+
);
|
|
356
|
+
useContextOptionsDeprecatedShown = true;
|
|
357
|
+
}
|
|
358
|
+
const opts = typeof options === "function" ? { compare: options } : options;
|
|
359
|
+
let ctxReader = contextReaders.get(name);
|
|
360
|
+
if (ctxReader === void 0) {
|
|
361
|
+
ctxReader = createSignal(void 0, opts).get;
|
|
362
|
+
contextReaders.set(name, ctxReader);
|
|
363
|
+
contextReaderCompares.set(name, opts?.compare);
|
|
364
|
+
const ln = link(entry.entity.useContext(name), ctxReader);
|
|
365
|
+
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
366
|
+
} else if (opts?.compare != null && contextReaderCompares.get(name) !== opts.compare) {
|
|
367
|
+
console.warn(
|
|
368
|
+
`[shadow-objects] useContext("${String(name)}"): the cached signal already exists with a different (or no) {compare} function \u2014 the new options are ignored. Pass options only on the first call per context.`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
return ctxReader;
|
|
372
|
+
},
|
|
373
|
+
useParentContext(name, options) {
|
|
374
|
+
if (!useParentContextOptionsDeprecatedShown && options != null && typeof options === "function") {
|
|
375
|
+
console.warn(
|
|
376
|
+
'[shadow-objects] Deprecation Warning: The "isEqual" option of "useParentContext()" is now passed as {compare} argument. Please update your code accordingly.'
|
|
377
|
+
);
|
|
378
|
+
useParentContextOptionsDeprecatedShown = true;
|
|
379
|
+
}
|
|
380
|
+
const opts = typeof options === "function" ? { compare: options } : options;
|
|
381
|
+
let ctxReader = contextParentReaders.get(name);
|
|
382
|
+
if (ctxReader === void 0) {
|
|
383
|
+
ctxReader = createSignal(void 0, opts).get;
|
|
384
|
+
contextParentReaders.set(name, ctxReader);
|
|
385
|
+
contextParentReaderCompares.set(name, opts?.compare);
|
|
386
|
+
const ln = link(entry.entity.useParentContext(name), ctxReader);
|
|
387
|
+
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
388
|
+
} else if (opts?.compare != null && contextParentReaderCompares.get(name) !== opts.compare) {
|
|
389
|
+
console.warn(
|
|
390
|
+
`[shadow-objects] useParentContext("${String(name)}"): the cached signal already exists with a different (or no) {compare} function \u2014 the new options are ignored. Pass options only on the first call per parent context.`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
return ctxReader;
|
|
394
|
+
},
|
|
395
|
+
dispatchMessageToView(type, data, transferables, traverseChildren = false) {
|
|
396
|
+
entry.entity.dispatchMessageToView(type, data, transferables, traverseChildren);
|
|
397
|
+
},
|
|
398
|
+
useProperty: getUseProperty,
|
|
399
|
+
useProperties(props) {
|
|
400
|
+
const result = {};
|
|
401
|
+
for (const key in props) {
|
|
402
|
+
if (Object.hasOwn(props, key)) {
|
|
403
|
+
result[key] = getUseProperty(props[key]);
|
|
493
404
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
if (
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
405
|
+
}
|
|
406
|
+
return result;
|
|
407
|
+
},
|
|
408
|
+
createResource(factory, cleanup) {
|
|
409
|
+
const resourceSignal = createSignal();
|
|
410
|
+
const effect = createEffect(() => {
|
|
411
|
+
const resource = toMaybe(factory());
|
|
412
|
+
resourceSignal.set(resource);
|
|
413
|
+
if (resource !== void 0 && cleanup) {
|
|
414
|
+
return () => {
|
|
415
|
+
cleanup(resource);
|
|
416
|
+
resourceSignal.set(void 0);
|
|
417
|
+
};
|
|
507
418
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
419
|
+
return () => {
|
|
420
|
+
resourceSignal.set(void 0);
|
|
421
|
+
};
|
|
422
|
+
});
|
|
423
|
+
unsubscribeSecondary.add(() => {
|
|
424
|
+
effect.destroy();
|
|
425
|
+
resourceSignal.set(void 0);
|
|
426
|
+
destroySignal(resourceSignal);
|
|
427
|
+
});
|
|
428
|
+
return resourceSignal;
|
|
429
|
+
},
|
|
430
|
+
createEffect(...args) {
|
|
431
|
+
const effect = createEffect(...args);
|
|
432
|
+
unsubscribeSecondary.add(effect.destroy);
|
|
433
|
+
return effect;
|
|
434
|
+
},
|
|
435
|
+
createSignal(...args) {
|
|
436
|
+
const sig = createSignal(...args);
|
|
437
|
+
unsubscribeSecondary.add(() => {
|
|
438
|
+
destroySignal(sig);
|
|
439
|
+
});
|
|
440
|
+
return sig;
|
|
441
|
+
},
|
|
442
|
+
createMemo(...args) {
|
|
443
|
+
const sig = createMemo(...args);
|
|
444
|
+
unsubscribeSecondary.add(() => {
|
|
445
|
+
destroySignal(sig);
|
|
446
|
+
});
|
|
447
|
+
return sig;
|
|
448
|
+
},
|
|
449
|
+
on(...args) {
|
|
450
|
+
const [firstArg] = args;
|
|
451
|
+
if (typeof firstArg === "string" || typeof firstArg === "symbol" || Array.isArray(firstArg)) {
|
|
452
|
+
const unsub2 = on(entry.entity, ...args);
|
|
453
|
+
unsubscribeSecondary.add(unsub2);
|
|
454
|
+
return unsub2;
|
|
455
|
+
}
|
|
456
|
+
const unsub = on(...args);
|
|
457
|
+
unsubscribeSecondary.add(unsub);
|
|
458
|
+
return Object.assign(() => {
|
|
459
|
+
unsubscribeSecondary.delete(unsub);
|
|
460
|
+
unsub();
|
|
461
|
+
}, unsub);
|
|
462
|
+
},
|
|
463
|
+
once(...args) {
|
|
464
|
+
const [firstArg] = args;
|
|
465
|
+
if (typeof firstArg === "string" || typeof firstArg === "symbol" || Array.isArray(firstArg)) {
|
|
466
|
+
const unsub2 = once(entry.entity, ...args);
|
|
467
|
+
unsubscribeSecondary.add(unsub2);
|
|
468
|
+
return unsub2;
|
|
469
|
+
}
|
|
470
|
+
const unsub = once(...args);
|
|
471
|
+
unsubscribeSecondary.add(unsub);
|
|
472
|
+
return Object.assign(() => {
|
|
473
|
+
unsubscribeSecondary.delete(unsub);
|
|
474
|
+
unsub();
|
|
475
|
+
}, unsub);
|
|
476
|
+
},
|
|
477
|
+
emit(...args) {
|
|
478
|
+
const [firstArg] = args;
|
|
479
|
+
if (typeof firstArg === "string" || typeof firstArg === "symbol" || Array.isArray(firstArg)) {
|
|
480
|
+
emit(entry.entity, ...args);
|
|
481
|
+
} else {
|
|
482
|
+
emit(...args);
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
onViewEvent(callback) {
|
|
486
|
+
const unsub = on(entry.entity, onViewEvent, (type, data) => {
|
|
487
|
+
callback(type, data);
|
|
488
|
+
});
|
|
489
|
+
unsubscribeSecondary.add(unsub);
|
|
490
|
+
},
|
|
491
|
+
onDestroy(callback) {
|
|
492
|
+
unsubscribePrimary.add(callback);
|
|
514
493
|
}
|
|
515
|
-
|
|
516
|
-
|
|
494
|
+
})
|
|
495
|
+
);
|
|
496
|
+
if (this.logger.isInfo) {
|
|
497
|
+
this.logger.info("create shadow-object", getDisplayName(construct), { shadowObject, entity: entry.entity });
|
|
498
|
+
}
|
|
499
|
+
once(entry.entity, onDestroy, Priority.Low, () => {
|
|
500
|
+
if (this.logger.isInfo) {
|
|
501
|
+
this.logger.info("destroy shadow-object", getDisplayName(construct), { shadowObject, entity: entry.entity });
|
|
502
|
+
}
|
|
503
|
+
for (const callback of unsubscribePrimary) {
|
|
504
|
+
callback();
|
|
505
|
+
}
|
|
506
|
+
for (const callback of unsubscribeSecondary) {
|
|
507
|
+
callback();
|
|
508
|
+
}
|
|
509
|
+
for (const sig of contextReaders.values()) {
|
|
510
|
+
destroySignal(sig);
|
|
511
|
+
}
|
|
512
|
+
for (const sig of contextParentReaders.values()) {
|
|
513
|
+
destroySignal(sig);
|
|
514
|
+
}
|
|
515
|
+
for (const sig of propertyReaders.values()) {
|
|
516
|
+
destroySignal(sig);
|
|
517
|
+
}
|
|
518
|
+
for (const sig of contextProviders.values()) {
|
|
519
|
+
destroySignal(sig);
|
|
520
|
+
}
|
|
521
|
+
for (const sig of contextRootProviders.values()) {
|
|
522
|
+
destroySignal(sig);
|
|
523
|
+
}
|
|
524
|
+
unsubscribePrimary.clear();
|
|
525
|
+
unsubscribeSecondary.clear();
|
|
526
|
+
contextReaders.clear();
|
|
527
|
+
contextParentReaders.clear();
|
|
528
|
+
propertyReaders.clear();
|
|
529
|
+
contextProviders.clear();
|
|
530
|
+
contextRootProviders.clear();
|
|
531
|
+
const otherShadowObjects = entry.usedConstructors.get(construct);
|
|
532
|
+
if (otherShadowObjects) {
|
|
533
|
+
otherShadowObjects.delete(shadowObject);
|
|
534
|
+
if (otherShadowObjects.size === 0) {
|
|
535
|
+
entry.usedConstructors.delete(construct);
|
|
517
536
|
}
|
|
518
|
-
|
|
519
|
-
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
if (entry.usedConstructors.has(construct)) {
|
|
540
|
+
entry.usedConstructors.get(construct).add(shadowObject);
|
|
541
|
+
} else {
|
|
542
|
+
entry.usedConstructors.set(construct, /* @__PURE__ */ new Set([shadowObject]));
|
|
520
543
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
544
|
+
this.attachShadowObject(shadowObject, entry.entity);
|
|
545
|
+
return shadowObject;
|
|
546
|
+
}
|
|
547
|
+
createShadowObjects(uuid) {
|
|
548
|
+
const entry = this.#entities.get(uuid);
|
|
549
|
+
this.registry.findConstructors(entry.token, entry.entity.truthyProps())?.forEach((construct) => {
|
|
550
|
+
this.constructShadowObject(construct, entry);
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
findShadowObjects(uuid) {
|
|
554
|
+
if (!this.#entities.has(uuid)) return [];
|
|
555
|
+
const { usedConstructors } = this.#entities.get(uuid);
|
|
556
|
+
return Array.from(new Set(Array.from(usedConstructors.values()).flatMap((objs) => Array.from(objs))));
|
|
557
|
+
}
|
|
558
|
+
attachShadowObject(shadowObject, entity) {
|
|
559
|
+
on(entity, shadowObject);
|
|
560
|
+
if (typeof shadowObject[onCreate] === "function") {
|
|
561
|
+
shadowObject[onCreate](entity);
|
|
526
562
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
return Array.from(new Set(Array.from(usedConstructors.values()).flatMap((objs) => Array.from(objs))));
|
|
563
|
+
}
|
|
564
|
+
destroyShadowObject(shadowObject, entity) {
|
|
565
|
+
if (typeof shadowObject[onDestroy] === "function") {
|
|
566
|
+
shadowObject[onDestroy](entity);
|
|
532
567
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
}
|
|
568
|
+
emit(shadowObject, onDestroy, entity);
|
|
569
|
+
off(entity, shadowObject);
|
|
570
|
+
}
|
|
571
|
+
findOrCreateRootContext(name) {
|
|
572
|
+
let ctx = this.#rootContexts.get(name);
|
|
573
|
+
if (!ctx) {
|
|
574
|
+
ctx = new SignalsPath();
|
|
575
|
+
this.#rootContexts.set(name, ctx);
|
|
542
576
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
off(entity, shadowObject);
|
|
549
|
-
}
|
|
550
|
-
findOrCreateRootContext(name) {
|
|
551
|
-
let ctx = this.#rootContexts.get(name);
|
|
552
|
-
if (!ctx) {
|
|
553
|
-
ctx = new SignalsPath();
|
|
554
|
-
this.#rootContexts.set(name, ctx);
|
|
555
|
-
}
|
|
556
|
-
return ctx;
|
|
577
|
+
return ctx;
|
|
578
|
+
}
|
|
579
|
+
destroy() {
|
|
580
|
+
for (const ctx of this.#rootContexts.values()) {
|
|
581
|
+
ctx.dispose();
|
|
557
582
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
}
|
|
562
|
-
this.#rootContexts.clear();
|
|
563
|
-
for (const entity of this.traverseLevelOrderBFS().reverse()) {
|
|
564
|
-
this.destroyEntity(entity.uuid);
|
|
565
|
-
}
|
|
583
|
+
this.#rootContexts.clear();
|
|
584
|
+
for (const entity of this.traverseLevelOrderBFS().reverse()) {
|
|
585
|
+
this.destroyEntity(entity.uuid);
|
|
566
586
|
}
|
|
587
|
+
}
|
|
567
588
|
}
|
|
568
|
-
|
|
589
|
+
export {
|
|
590
|
+
Kernel
|
|
591
|
+
};
|
|
592
|
+
//# sourceMappingURL=Kernel.js.map
|