Skip to content

Commit fb27c3a

Browse files
committed
⏪ whoops
1 parent 882be4a commit fb27c3a

File tree

9 files changed

+64
-28
lines changed

9 files changed

+64
-28
lines changed

packages/core/src/entity/entity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,5 @@ export function destroyEntity(world: World, entity: Entity) {
110110

111111
/* @inline @pure */ export function getEntityWorld(entity: Entity) {
112112
const worldId = getEntityWorldId(entity);
113-
return universe.worlds[worldId]!.deref()!;
113+
return universe.worlds[worldId]!;
114114
}

packages/core/src/query/modifiers/added.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function createAdded() {
88

99
for (const world of universe.worlds) {
1010
if (!world) continue;
11-
setTrackingMasks(world.deref()!, id);
11+
setTrackingMasks(world, id);
1212
}
1313

1414
return <T extends Trait[] = Trait[]>(...traits: T) => {

packages/core/src/query/modifiers/changed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function createChanged() {
1313

1414
for (const world of universe.worlds) {
1515
if (!world) continue;
16-
setTrackingMasks(world.deref()!, id);
16+
setTrackingMasks(world, id);
1717
}
1818

1919
return <T extends Trait[] = Trait[]>(...traits: T) => {

packages/core/src/query/modifiers/removed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function createRemoved() {
88

99
for (const world of universe.worlds) {
1010
if (!world) continue;
11-
setTrackingMasks(world.deref()!, id);
11+
setTrackingMasks(world, id);
1212
}
1313

1414
return <T extends Trait[] = Trait[]>(...traits: T) => {

packages/core/src/query/utils/cache-query.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import { createQueryHash } from './create-query-hash';
77
export function cacheQuery<T extends QueryParameter[]>(...parameters: T): QueryHash<T> {
88
const hash = createQueryHash(parameters);
99

10-
for (const worldRef of universe.worlds) {
11-
if (!worldRef) continue;
10+
for (const world of universe.worlds) {
11+
if (!world) continue;
1212

13-
const world = worldRef.deref()!;
1413
const ctx = world[$internal];
1514

1615
if (!ctx.queriesHashMap.has(hash)) {

packages/core/src/universe/universe.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
import { WORLD_ID_BITS } from '../entity/utils/pack-entity';
21
import type { QueryParameter } from '../query/types';
32
import { createWorldIndex } from '../world/utils/world-index';
43
import type { World } from '../world/world';
54

65
export const universe = {
7-
worlds: Array.from({ length: WORLD_ID_BITS ** 2 }, () => null as WeakRef<World> | null),
6+
worlds: [] as (World | null)[],
87
cachedQueries: new Map<string, QueryParameter[]>(),
98
worldIndex: createWorldIndex(),
109
reset: () => {
11-
universe.worlds = Array.from(
12-
{ length: WORLD_ID_BITS ** 2 },
13-
() => null as WeakRef<World> | null
14-
);
10+
universe.worlds = [];
1511
universe.cachedQueries = new Map();
1612
universe.worldIndex = createWorldIndex();
1713
},

packages/core/src/world/world.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ import type {
2121
import { universe } from '../universe/universe';
2222
import { allocateWorldId, releaseWorldId } from './utils/world-index';
2323

24+
type Options = {
25+
traits?: ConfigurableTrait[];
26+
lazy?: boolean;
27+
};
28+
2429
export class World {
2530
#id = allocateWorldId(universe.worldIndex);
2631

@@ -58,16 +63,21 @@ export class World {
5863

5964
traits = new Set<Trait>();
6065

61-
constructor(...traits: ConfigurableTrait[]) {
62-
this.init(...traits);
66+
constructor(polyArg?: Options | ConfigurableTrait, ...traits: ConfigurableTrait[]) {
67+
if (polyArg && typeof polyArg === 'object' && !Array.isArray(polyArg)) {
68+
const { traits: optionTraits = [], lazy = false } = polyArg as Options;
69+
if (!lazy) this.init(...optionTraits);
70+
} else {
71+
this.init(...(polyArg ? [polyArg, ...traits] : traits));
72+
}
6373
}
6474

6575
init(...traits: ConfigurableTrait[]) {
6676
const ctx = this[$internal];
6777
if (this.#isInitialized) return;
6878

6979
this.#isInitialized = true;
70-
universe.worlds[this.#id] = new WeakRef(this);
80+
universe.worlds[this.#id] = this;
7181

7282
// Create uninitialized added masks.
7383
const cursor = getTrackingCursor();
@@ -313,14 +323,11 @@ export class World {
313323
}
314324
}
315325

316-
// Clean up the world ID when it is garbage collected.
317-
const worldFinalizer = new FinalizationRegistry((worldId: number) => {
318-
universe.worlds[worldId] = null;
319-
releaseWorldId(universe.worldIndex, worldId);
320-
});
321-
322-
export function createWorld(...traits: ConfigurableTrait[]) {
323-
const world = new World(...traits);
324-
worldFinalizer.register(world, world.id);
325-
return world;
326+
export function createWorld(options: Options): World;
327+
export function createWorld(...traits: ConfigurableTrait[]): World;
328+
export function createWorld(
329+
optionsOrFirstTrait?: Options | ConfigurableTrait,
330+
...traits: ConfigurableTrait[]
331+
) {
332+
return new World(optionsOrFirstTrait, ...traits);
326333
}

packages/core/tests/world.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ describe('World', () => {
1212

1313
expect(world.isInitialized).toBe(true);
1414
expect(world.id).toBe(0);
15-
expect(universe.worlds[0]!.deref()!).toBe(world);
15+
expect(universe.worlds[0]!).toBe(world);
1616
expect(universe.worldIndex.worldCursor).toBe(1);
1717
});
1818

19+
it('should optionaly init lazily', () => {
20+
const world = createWorld({ lazy: true });
21+
expect(world.isInitialized).toBe(false);
22+
world.init();
23+
expect(world.isInitialized).toBe(true);
24+
});
25+
1926
it('should reset the world', () => {
2027
const world = createWorld();
2128
world.reset();

packages/react/tests/world.test.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createWorld, universe, type World } from '@koota/core';
22
import { render } from '@testing-library/react';
3-
import { act, StrictMode } from 'react';
3+
import { act, StrictMode, useEffect, useMemo } from 'react';
44
import { beforeEach, describe, expect, it } from 'vitest';
55
import { useWorld, WorldProvider } from '../src';
66

@@ -39,4 +39,31 @@ describe('World', () => {
3939

4040
expect(worldTest).toBe(world);
4141
});
42+
43+
it('can lazy init to create a world in useMemo', () => {
44+
universe.reset();
45+
46+
let worldTest: World = null!;
47+
48+
function Test() {
49+
worldTest = useMemo(() => createWorld({ lazy: true }), []);
50+
51+
useEffect(() => {
52+
worldTest.init();
53+
return () => worldTest.destroy();
54+
}, [worldTest]);
55+
56+
return null;
57+
}
58+
59+
render(
60+
<StrictMode>
61+
<Test />
62+
</StrictMode>
63+
);
64+
65+
expect(worldTest).toBeDefined();
66+
expect(worldTest!.isInitialized).toBe(true);
67+
expect(universe.worlds.length).toBe(1);
68+
});
4269
});

0 commit comments

Comments
 (0)