@spearwolf/shadow-objects 0.30.2 → 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 +18 -0
- 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 +1 -1
- package/src/in-the-dark/Entity.d.ts.map +1 -1
- package/src/in-the-dark/Entity.js +299 -293
- package/src/in-the-dark/Entity.js.map +7 -1
- package/src/in-the-dark/Kernel.d.ts.map +1 -1
- package/src/in-the-dark/Kernel.js +556 -533
- 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 +3 -2
- 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,569 +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
|
-
}
|
|
159
|
-
if (properties) {
|
|
160
|
-
e.setProperties(properties);
|
|
161
|
-
}
|
|
162
|
-
this.createShadowObjects(uuid);
|
|
163
|
-
}
|
|
164
|
-
destroyEntity(uuid) {
|
|
165
|
-
if (!this.#entities.has(uuid))
|
|
166
|
-
return;
|
|
167
|
-
const { entity, usedConstructors } = this.#entities.get(uuid);
|
|
168
|
-
entity.removeFromParent();
|
|
169
|
-
emit(entity, onDestroy, entity);
|
|
170
|
-
usedConstructors.clear();
|
|
171
|
-
this.#entities.delete(entity.uuid);
|
|
172
|
-
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;
|
|
173
149
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
this.#rootEntities.delete(uuid);
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
this.#rootEntities.add(uuid);
|
|
186
|
-
}
|
|
187
|
-
e.reSubscribeToParentContexts();
|
|
188
|
-
queueMicrotask(() => {
|
|
189
|
-
if (this.logger.isDebug) {
|
|
190
|
-
this.logger.debug('entity.onParentChanged', { uuid, parentUuid, order, entity: e });
|
|
191
|
-
}
|
|
192
|
-
emit(e, onParentChanged, e);
|
|
193
|
-
});
|
|
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;
|
|
194
158
|
}
|
|
195
|
-
|
|
196
|
-
|
|
159
|
+
e.autoDestructionOnParentRemoval = autoDestructionOnParentRemoval;
|
|
160
|
+
if (!e.hasParent) {
|
|
161
|
+
this.#rootEntities.add(uuid);
|
|
197
162
|
}
|
|
198
|
-
|
|
199
|
-
|
|
163
|
+
if (properties) {
|
|
164
|
+
e.setProperties(properties);
|
|
200
165
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
+
}
|
|
204
179
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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!`);
|
|
213
192
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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);
|
|
218
200
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
+
}
|
|
239
247
|
}
|
|
240
|
-
|
|
241
|
-
//
|
|
242
|
-
if (shouldCreate) {
|
|
243
|
-
for (const construct of nextConstructors) {
|
|
244
|
-
if (!entry.usedConstructors.has(construct)) {
|
|
245
|
-
this.constructShadowObject(construct, entry);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return nextConstructors;
|
|
248
|
+
}
|
|
250
249
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const contextParentReaders = new Map();
|
|
256
|
-
const contextProviders = new Map();
|
|
257
|
-
const contextRootProviders = new Map();
|
|
258
|
-
const propertyReaders = new Map();
|
|
259
|
-
const getUseProperty = (name, options) => {
|
|
260
|
-
if (!usePropertyOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
261
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "useProperty()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
262
|
-
usePropertyOptionsDeprecatedShown = true;
|
|
263
|
-
}
|
|
264
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
265
|
-
let propReader = propertyReaders.get(name);
|
|
266
|
-
if (propReader === undefined) {
|
|
267
|
-
propReader = createSignal(undefined, opts).get;
|
|
268
|
-
propertyReaders.set(name, propReader);
|
|
269
|
-
const con = link(entry.entity.getPropertyReader(name), propReader);
|
|
270
|
-
unsubscribeSecondary.add(con.destroy.bind(con));
|
|
271
|
-
}
|
|
272
|
-
return propReader;
|
|
273
|
-
};
|
|
274
|
-
const shadowObject = eventize(new construct({
|
|
275
|
-
entity: entry.entity,
|
|
276
|
-
provideContext(name, sourceOrInitialValue, options) {
|
|
277
|
-
if (!provideContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
278
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "provideContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
279
|
-
provideContextOptionsDeprecatedShown = true;
|
|
280
|
-
}
|
|
281
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
282
|
-
let ctxProvider = contextProviders.get(name);
|
|
283
|
-
if (ctxProvider == null) {
|
|
284
|
-
const isSig = isSignal(sourceOrInitialValue);
|
|
285
|
-
const initialValue = isSig ? undefined : toMaybe(sourceOrInitialValue);
|
|
286
|
-
ctxProvider = createSignal(initialValue, opts?.compare ? { compare: opts.compare } : undefined);
|
|
287
|
-
if (isSig) {
|
|
288
|
-
const ln = link(sourceOrInitialValue, ctxProvider);
|
|
289
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
290
|
-
}
|
|
291
|
-
const ln = link(ctxProvider, entry.entity.provideContext(name));
|
|
292
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
293
|
-
contextProviders.set(name, ctxProvider);
|
|
294
|
-
}
|
|
295
|
-
if (ctxProvider != null && (opts?.clearOnDestroy ?? true)) {
|
|
296
|
-
unsubscribeSecondary.add(() => {
|
|
297
|
-
ctxProvider.set(undefined);
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
return ctxProvider;
|
|
301
|
-
},
|
|
302
|
-
provideGlobalContext(name, sourceOrInitialValue, options) {
|
|
303
|
-
if (!provideGlobalContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
304
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "provideGlobalContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
305
|
-
provideGlobalContextOptionsDeprecatedShown = true;
|
|
306
|
-
}
|
|
307
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
308
|
-
let ctxProvider = contextRootProviders.get(name);
|
|
309
|
-
if (ctxProvider == null) {
|
|
310
|
-
const isSig = isSignal(sourceOrInitialValue);
|
|
311
|
-
const initialValue = isSig ? undefined : toMaybe(sourceOrInitialValue);
|
|
312
|
-
ctxProvider = createSignal(initialValue, opts?.compare ? { compare: opts.compare } : undefined);
|
|
313
|
-
if (isSig) {
|
|
314
|
-
const ln = link(sourceOrInitialValue, ctxProvider);
|
|
315
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
316
|
-
}
|
|
317
|
-
const ln = link(ctxProvider, entry.entity.provideGlobalContext(name));
|
|
318
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
319
|
-
contextRootProviders.set(name, ctxProvider);
|
|
320
|
-
}
|
|
321
|
-
if (ctxProvider != null && (opts?.clearOnDestroy ?? true)) {
|
|
322
|
-
unsubscribeSecondary.add(() => {
|
|
323
|
-
ctxProvider.set(undefined);
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
return ctxProvider;
|
|
327
|
-
},
|
|
328
|
-
useContext(name, options) {
|
|
329
|
-
if (!useContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
330
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "useContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
331
|
-
useContextOptionsDeprecatedShown = true;
|
|
332
|
-
}
|
|
333
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
334
|
-
let ctxReader = contextReaders.get(name);
|
|
335
|
-
if (ctxReader === undefined) {
|
|
336
|
-
ctxReader = createSignal(undefined, opts).get;
|
|
337
|
-
contextReaders.set(name, ctxReader);
|
|
338
|
-
const ln = link(entry.entity.useContext(name), ctxReader);
|
|
339
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
340
|
-
}
|
|
341
|
-
return ctxReader;
|
|
342
|
-
},
|
|
343
|
-
useParentContext(name, options) {
|
|
344
|
-
if (!useParentContextOptionsDeprecatedShown && options != null && typeof options === 'function') {
|
|
345
|
-
console.warn('[shadow-objects] Deprecation Warning: The "isEqual" option of "useParentContext()" is now passed as {compare} argument. Please update your code accordingly.');
|
|
346
|
-
useParentContextOptionsDeprecatedShown = true;
|
|
347
|
-
}
|
|
348
|
-
const opts = typeof options === 'function' ? { compare: options } : options;
|
|
349
|
-
let ctxReader = contextParentReaders.get(name);
|
|
350
|
-
if (ctxReader === undefined) {
|
|
351
|
-
ctxReader = createSignal(undefined, opts).get;
|
|
352
|
-
contextParentReaders.set(name, ctxReader);
|
|
353
|
-
const ln = link(entry.entity.useParentContext(name), ctxReader);
|
|
354
|
-
unsubscribeSecondary.add(ln.destroy.bind(ln));
|
|
355
|
-
}
|
|
356
|
-
return ctxReader;
|
|
357
|
-
},
|
|
358
|
-
dispatchMessageToView(type, data, transferables, traverseChildren = false) {
|
|
359
|
-
entry.entity.dispatchMessageToView(type, data, transferables, traverseChildren);
|
|
360
|
-
},
|
|
361
|
-
useProperty: getUseProperty,
|
|
362
|
-
useProperties(props) {
|
|
363
|
-
const result = {};
|
|
364
|
-
for (const key in props) {
|
|
365
|
-
if (Object.hasOwn(props, key)) {
|
|
366
|
-
result[key] = getUseProperty(props[key]);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return result;
|
|
370
|
-
},
|
|
371
|
-
createResource(factory, cleanup) {
|
|
372
|
-
const resourceSignal = createSignal();
|
|
373
|
-
const effect = createEffect(() => {
|
|
374
|
-
const resource = toMaybe(factory());
|
|
375
|
-
resourceSignal.set(resource);
|
|
376
|
-
if (resource !== undefined && cleanup) {
|
|
377
|
-
return () => {
|
|
378
|
-
cleanup(resource);
|
|
379
|
-
resourceSignal.set(undefined);
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
return () => {
|
|
383
|
-
resourceSignal.set(undefined);
|
|
384
|
-
};
|
|
385
|
-
});
|
|
386
|
-
unsubscribeSecondary.add(() => {
|
|
387
|
-
effect.destroy();
|
|
388
|
-
resourceSignal.set(undefined);
|
|
389
|
-
destroySignal(resourceSignal);
|
|
390
|
-
});
|
|
391
|
-
return resourceSignal;
|
|
392
|
-
},
|
|
393
|
-
createEffect(...args) {
|
|
394
|
-
const effect = createEffect(...args);
|
|
395
|
-
unsubscribeSecondary.add(effect.destroy);
|
|
396
|
-
return effect;
|
|
397
|
-
},
|
|
398
|
-
createSignal(...args) {
|
|
399
|
-
const sig = createSignal(...args);
|
|
400
|
-
unsubscribeSecondary.add(() => {
|
|
401
|
-
destroySignal(sig);
|
|
402
|
-
});
|
|
403
|
-
return sig;
|
|
404
|
-
},
|
|
405
|
-
createMemo(...args) {
|
|
406
|
-
const sig = createMemo(...args);
|
|
407
|
-
unsubscribeSecondary.add(() => {
|
|
408
|
-
destroySignal(sig);
|
|
409
|
-
});
|
|
410
|
-
return sig;
|
|
411
|
-
},
|
|
412
|
-
on(...args) {
|
|
413
|
-
const [firstArg] = args;
|
|
414
|
-
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
|
|
415
|
-
// @ts-ignore
|
|
416
|
-
const unsub = on(entry.entity, ...args);
|
|
417
|
-
unsubscribeSecondary.add(unsub);
|
|
418
|
-
return unsub;
|
|
419
|
-
}
|
|
420
|
-
// @ts-ignore
|
|
421
|
-
const unsub = on(...args);
|
|
422
|
-
unsubscribeSecondary.add(unsub);
|
|
423
|
-
// return unsub;
|
|
424
|
-
return Object.assign(() => {
|
|
425
|
-
unsubscribeSecondary.delete(unsub);
|
|
426
|
-
unsub();
|
|
427
|
-
}, unsub);
|
|
428
|
-
},
|
|
429
|
-
once(...args) {
|
|
430
|
-
const [firstArg] = args;
|
|
431
|
-
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
|
|
432
|
-
// @ts-ignore
|
|
433
|
-
const unsub = once(entry.entity, ...args);
|
|
434
|
-
unsubscribeSecondary.add(unsub);
|
|
435
|
-
return unsub;
|
|
436
|
-
}
|
|
437
|
-
// @ts-ignore
|
|
438
|
-
const unsub = once(...args);
|
|
439
|
-
unsubscribeSecondary.add(unsub);
|
|
440
|
-
// return unsub;
|
|
441
|
-
return Object.assign(() => {
|
|
442
|
-
unsubscribeSecondary.delete(unsub);
|
|
443
|
-
unsub();
|
|
444
|
-
}, unsub);
|
|
445
|
-
},
|
|
446
|
-
emit(...args) {
|
|
447
|
-
const [firstArg] = args;
|
|
448
|
-
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
|
|
449
|
-
// @ts-ignore
|
|
450
|
-
emit(entry.entity, ...args);
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
// @ts-ignore
|
|
454
|
-
emit(...args);
|
|
455
|
-
}
|
|
456
|
-
},
|
|
457
|
-
onViewEvent(callback) {
|
|
458
|
-
const unsub = on(entry.entity, onViewEvent, (type, data) => {
|
|
459
|
-
callback(type, data);
|
|
460
|
-
});
|
|
461
|
-
unsubscribeSecondary.add(unsub);
|
|
462
|
-
},
|
|
463
|
-
onDestroy(callback) {
|
|
464
|
-
unsubscribePrimary.add(callback);
|
|
465
|
-
},
|
|
466
|
-
}));
|
|
467
|
-
if (this.logger.isInfo) {
|
|
468
|
-
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);
|
|
469
254
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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));
|
|
488
311
|
}
|
|
489
|
-
|
|
490
|
-
|
|
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));
|
|
491
339
|
}
|
|
492
|
-
|
|
493
|
-
|
|
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]);
|
|
494
404
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
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
|
+
};
|
|
508
418
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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);
|
|
515
493
|
}
|
|
516
|
-
|
|
517
|
-
|
|
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);
|
|
518
536
|
}
|
|
519
|
-
|
|
520
|
-
|
|
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]));
|
|
521
543
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
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);
|
|
527
562
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
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);
|
|
533
567
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
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);
|
|
543
576
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
off(entity, shadowObject);
|
|
550
|
-
}
|
|
551
|
-
findOrCreateRootContext(name) {
|
|
552
|
-
let ctx = this.#rootContexts.get(name);
|
|
553
|
-
if (!ctx) {
|
|
554
|
-
ctx = new SignalsPath();
|
|
555
|
-
this.#rootContexts.set(name, ctx);
|
|
556
|
-
}
|
|
557
|
-
return ctx;
|
|
577
|
+
return ctx;
|
|
578
|
+
}
|
|
579
|
+
destroy() {
|
|
580
|
+
for (const ctx of this.#rootContexts.values()) {
|
|
581
|
+
ctx.dispose();
|
|
558
582
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
this.#rootContexts.clear();
|
|
564
|
-
for (const entity of this.traverseLevelOrderBFS().reverse()) {
|
|
565
|
-
this.destroyEntity(entity.uuid);
|
|
566
|
-
}
|
|
583
|
+
this.#rootContexts.clear();
|
|
584
|
+
for (const entity of this.traverseLevelOrderBFS().reverse()) {
|
|
585
|
+
this.destroyEntity(entity.uuid);
|
|
567
586
|
}
|
|
587
|
+
}
|
|
568
588
|
}
|
|
569
|
-
|
|
589
|
+
export {
|
|
590
|
+
Kernel
|
|
591
|
+
};
|
|
592
|
+
//# sourceMappingURL=Kernel.js.map
|