@@ -31,7 +31,8 @@ enum JavaScriptValueKind {
3131
3232export class SwiftRuntime {
3333 private instance : WebAssembly . Instance | null ;
34- private _heapValues : any [ ]
34+ private _heapValues : Map < number , any > ;
35+ private _heapNextKey : number ;
3536
3637 constructor ( ) {
3738 this . instance = null ;
@@ -41,9 +42,10 @@ export class SwiftRuntime {
4142 } else if ( typeof global !== "undefined" ) {
4243 _global = global
4344 }
44- this . _heapValues = [
45- _global ,
46- ]
45+ this . _heapValues = new Map ( ) ;
46+ this . _heapValues . set ( 0 , _global ) ;
47+ // Note: 0 is preserved for global
48+ this . _heapNextKey = 1 ;
4749 }
4850
4951 setInsance ( instance : WebAssembly . Instance ) {
@@ -57,13 +59,31 @@ export class SwiftRuntime {
5759 throw new Error ( "WebAssembly instance is not set yet" ) ;
5860 }
5961
60- const allocValue = ( value : any ) => {
61- // TODO
62- const id = this . _heapValues . length
63- this . _heapValues . push ( value )
62+ const allocHeap = ( value : any ) => {
63+ const isObject = typeof value == "object"
64+ if ( isObject && value . swjs_heap_id ) {
65+ return value . swjs_heap_id
66+ }
67+ const id = this . _heapNextKey ++ ;
68+ this . _heapValues . set ( id , value )
69+ if ( isObject )
70+ Reflect . set ( value , "swjs_heap_id" , id ) ;
6471 return id
6572 }
6673
74+ const freeHeap = ( ref : ref ) => {
75+ const value = this . _heapValues . get ( ref ) ;
76+ const isObject = typeof value == "object"
77+ if ( isObject && value . swjs_heap_id ) {
78+ delete value . swjs_heap_id ;
79+ }
80+ this . _heapValues . delete ( ref )
81+ }
82+
83+ const referenceHeap = ( ref : ref ) => {
84+ return this . _heapValues . get ( ref )
85+ }
86+
6787 const callHostFunction = ( host_func_id : number , args : any [ ] ) => {
6888 if ( ! this . instance )
6989 throw new Error ( "WebAssembly instance is not set yet" ) ;
@@ -79,7 +99,7 @@ export class SwiftRuntime {
7999 writeUint32 ( base + 8 , value . payload2 )
80100 }
81101 let output : any ;
82- const callback_func_ref = allocValue ( function ( result : any ) {
102+ const callback_func_ref = allocHeap ( function ( result : any ) {
83103 output = result
84104 } )
85105 exports . swjs_call_host_function ( host_func_id , argv , argc , callback_func_ref )
@@ -137,7 +157,7 @@ export class SwiftRuntime {
137157 return readString ( payload1 , payload2 )
138158 }
139159 case JavaScriptValueKind . Object : {
140- return this . _heapValues [ payload1 ]
160+ return referenceHeap ( payload1 )
141161 }
142162 case JavaScriptValueKind . Null : {
143163 return null
@@ -146,7 +166,7 @@ export class SwiftRuntime {
146166 return undefined
147167 }
148168 case JavaScriptValueKind . Function : {
149- return this . _heapValues [ payload1 ]
169+ return referenceHeap ( payload1 )
150170 }
151171 default :
152172 throw new Error ( `Type kind "${ kind } " is not supported` )
@@ -179,7 +199,7 @@ export class SwiftRuntime {
179199 case "string" : {
180200 return {
181201 kind : JavaScriptValueKind . String ,
182- payload1 : allocValue ( value ) ,
202+ payload1 : allocHeap ( value ) ,
183203 payload2 : value . length ,
184204 }
185205 }
@@ -193,14 +213,14 @@ export class SwiftRuntime {
193213 case "object" : {
194214 return {
195215 kind : JavaScriptValueKind . Object ,
196- payload1 : allocValue ( value ) ,
216+ payload1 : allocHeap ( value ) ,
197217 payload2 : 0 ,
198218 }
199219 }
200220 case "function" : {
201221 return {
202222 kind : JavaScriptValueKind . Function ,
203- payload1 : allocValue ( value ) ,
223+ payload1 : allocHeap ( value ) ,
204224 payload2 : 0 ,
205225 }
206226 }
@@ -230,15 +250,15 @@ export class SwiftRuntime {
230250 kind : JavaScriptValueKind ,
231251 payload1 : number , payload2 : number
232252 ) => {
233- const obj = this . _heapValues [ ref ] ;
253+ const obj = referenceHeap ( ref ) ;
234254 Reflect . set ( obj , readString ( name , length ) , decodeValue ( kind , payload1 , payload2 ) )
235255 } ,
236256 swjs_get_prop : (
237257 ref : ref , name : pointer , length : number ,
238258 kind_ptr : pointer ,
239259 payload1_ptr : pointer , payload2_ptr : pointer
240260 ) => {
241- const obj = this . _heapValues [ ref ] ;
261+ const obj = referenceHeap ( ref ) ;
242262 const result = Reflect . get ( obj , readString ( name , length ) ) ;
243263 const { kind, payload1, payload2 } = encodeValue ( result ) ;
244264 writeUint32 ( kind_ptr , kind ) ;
@@ -250,31 +270,31 @@ export class SwiftRuntime {
250270 kind : JavaScriptValueKind ,
251271 payload1 : number , payload2 : number
252272 ) => {
253- const obj = this . _heapValues [ ref ] ;
273+ const obj = referenceHeap ( ref ) ;
254274 Reflect . set ( obj , index , decodeValue ( kind , payload1 , payload2 ) )
255275 } ,
256276 swjs_get_subscript : (
257277 ref : ref , index : number ,
258278 kind_ptr : pointer ,
259279 payload1_ptr : pointer , payload2_ptr : pointer
260280 ) => {
261- const obj = this . _heapValues [ ref ] ;
281+ const obj = referenceHeap ( ref ) ;
262282 const result = Reflect . get ( obj , index ) ;
263283 const { kind, payload1, payload2 } = encodeValue ( result ) ;
264284 writeUint32 ( kind_ptr , kind ) ;
265285 writeUint32 ( payload1_ptr , payload1 ) ;
266286 writeUint32 ( payload2_ptr , payload2 ) ;
267287 } ,
268288 swjs_load_string : ( ref : ref , buffer : pointer ) => {
269- const string = this . _heapValues [ ref ] ;
289+ const string = referenceHeap ( ref ) ;
270290 writeString ( buffer , string ) ;
271291 } ,
272292 swjs_call_function : (
273293 ref : ref , argv : pointer , argc : number ,
274294 kind_ptr : pointer ,
275295 payload1_ptr : pointer , payload2_ptr : pointer
276296 ) => {
277- const func = this . _heapValues [ ref ]
297+ const func = referenceHeap ( ref )
278298 const result = Reflect . apply ( func , undefined , decodeValues ( argv , argc ) )
279299 const { kind, payload1, payload2 } = encodeValue ( result ) ;
280300 writeUint32 ( kind_ptr , kind ) ;
@@ -287,8 +307,8 @@ export class SwiftRuntime {
287307 kind_ptr : pointer ,
288308 payload1_ptr : pointer , payload2_ptr : pointer
289309 ) => {
290- const obj = this . _heapValues [ obj_ref ]
291- const func = this . _heapValues [ func_ref ]
310+ const obj = referenceHeap ( obj_ref )
311+ const func = referenceHeap ( func_ref )
292312 const result = Reflect . apply ( func , obj , decodeValues ( argv , argc ) )
293313 const { kind, payload1, payload2 } = encodeValue ( result ) ;
294314 writeUint32 ( kind_ptr , kind ) ;
@@ -299,7 +319,7 @@ export class SwiftRuntime {
299319 host_func_id : number ,
300320 func_ref_ptr : pointer ,
301321 ) => {
302- const func_ref = allocValue ( function ( ) {
322+ const func_ref = allocHeap ( function ( ) {
303323 return callHostFunction ( host_func_id , Array . prototype . slice . call ( arguments ) )
304324 } )
305325 writeUint32 ( func_ref_ptr , func_ref )
@@ -308,12 +328,15 @@ export class SwiftRuntime {
308328 ref : ref , argv : pointer , argc : number ,
309329 result_obj : pointer
310330 ) => {
311- const obj = this . _heapValues [ ref ]
331+ const obj = referenceHeap ( ref )
312332 const result = Reflect . construct ( obj , decodeValues ( argv , argc ) )
313333 if ( typeof result != "object" )
314334 throw Error ( `Invalid result type of object constructor of "${ obj } ": "${ result } "` )
315- writeUint32 ( result_obj , allocValue ( result ) ) ;
335+ writeUint32 ( result_obj , allocHeap ( result ) ) ;
316336 } ,
337+ swjs_destroy_ref : ( ref : ref ) => {
338+ freeHeap ( ref )
339+ }
317340 }
318341 }
319342}
0 commit comments