@@ -2,66 +2,74 @@ import { globalVariable } from "../src/find-global.js";
22import { ref } from "../src/types.js" ;
33
44export class JSObjectSpace_v2 {
5- private _entryByValue : Map < any , { id : number ; rc : number } > ;
6- private _values : ( any | undefined ) [ ] ;
7- private _refCounts : number [ ] ;
5+ private _idByValue : Map < any , number > ;
6+ private _valueById : Record < number , any > ;
7+ private _refCountById : Record < number , number | undefined > ;
88 private _nextRef : number ;
99
1010 constructor ( ) {
11- this . _values = [ ] ;
12- this . _values [ 0 ] = undefined ;
13- this . _values [ 1 ] = globalVariable ;
14-
15- this . _entryByValue = new Map ( ) ;
16- this . _entryByValue . set ( globalVariable , { id : 1 , rc : 1 } ) ;
17-
18- this . _refCounts = [ ] ;
19- this . _refCounts [ 0 ] = 0 ;
20- this . _refCounts [ 1 ] = 1 ;
11+ this . _idByValue = new Map ( ) ;
12+ this . _idByValue . set ( globalVariable , 1 ) ;
13+ this . _valueById = Object . create ( null ) ;
14+ this . _refCountById = Object . create ( null ) ;
15+ this . _valueById [ 1 ] = globalVariable ;
16+ this . _refCountById [ 1 ] = 1 ;
2117
2218 // 0 is invalid, 1 is globalThis.
2319 this . _nextRef = 2 ;
2420 }
2521
2622 retain ( value : any ) {
27- const entry = this . _entryByValue . get ( value ) ;
28- if ( entry ) {
29- entry . rc ++ ;
30- this . _refCounts [ entry . id ] ++ ;
31- return entry . id ;
23+ const id = this . _idByValue . get ( value ) ;
24+ if ( id !== undefined ) {
25+ this . _refCountById [ id ] ! ++ ;
26+ return id ;
3227 }
3328
34- const id = this . _nextRef ++ ;
35- this . _values [ id ] = value ;
36- this . _refCounts [ id ] = 1 ;
37- this . _entryByValue . set ( value , { id , rc : 1 } ) ;
38- return id ;
29+ const newId = this . _nextRef ++ ;
30+ this . _valueById [ newId ] = value ;
31+ this . _refCountById [ newId ] = 1 ;
32+ this . _idByValue . set ( value , newId ) ;
33+ return newId ;
3934 }
4035
4136 retainByRef ( ref : ref ) {
42- return this . retain ( this . getObject ( ref ) ) ;
37+ const rc = this . _refCountById [ ref ] ;
38+ if ( rc === undefined ) {
39+ throw new ReferenceError (
40+ "Attempted to retain invalid reference " + ref ,
41+ ) ;
42+ }
43+ this . _refCountById [ ref ] = rc + 1 ;
44+ return ref ;
4345 }
4446
4547 release ( ref : ref ) {
46- const value = this . _values [ ref ] ;
47- const entry = this . _entryByValue . get ( value ) ! ;
48- entry . rc -- ;
49- this . _refCounts [ ref ] -- ;
50- if ( entry . rc != 0 ) return ;
48+ const rc = this . _refCountById [ ref ] ;
49+ if ( rc === undefined ) {
50+ throw new ReferenceError (
51+ "Attempted to release invalid reference " + ref ,
52+ ) ;
53+ }
54+ const next = rc - 1 ;
55+ if ( next !== 0 ) {
56+ this . _refCountById [ ref ] = next ;
57+ return ;
58+ }
5159
52- this . _entryByValue . delete ( value ) ;
53- // Keep IDs monotonic; clear slot and leave possible holes.
54- this . _values [ ref ] = undefined ;
55- this . _refCounts [ ref ] = 0 ;
60+ const value = this . _valueById [ ref ] ;
61+ this . _idByValue . delete ( value ) ;
62+ delete this . _valueById [ ref ] ;
63+ delete this . _refCountById [ ref ] ;
5664 }
5765
5866 getObject ( ref : ref ) {
59- const value = this . _values [ ref ] ;
60- if ( value === undefined ) {
67+ const rc = this . _refCountById [ ref ] ;
68+ if ( rc === undefined ) {
6169 throw new ReferenceError (
6270 "Attempted to read invalid reference " + ref ,
6371 ) ;
6472 }
65- return value ;
73+ return this . _valueById [ ref ] ;
6674 }
6775}
0 commit comments