@@ -31,7 +31,8 @@ enum JavaScriptValueKind {
31
31
32
32
export class SwiftRuntime {
33
33
private instance : WebAssembly . Instance | null ;
34
- private _heapValues : any [ ]
34
+ private _heapValues : Map < number , any > ;
35
+ private _heapNextKey : number ;
35
36
36
37
constructor ( ) {
37
38
this . instance = null ;
@@ -41,9 +42,10 @@ export class SwiftRuntime {
41
42
} else if ( typeof global !== "undefined" ) {
42
43
_global = global
43
44
}
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 ;
47
49
}
48
50
49
51
setInsance ( instance : WebAssembly . Instance ) {
@@ -57,13 +59,31 @@ export class SwiftRuntime {
57
59
throw new Error ( "WebAssembly instance is not set yet" ) ;
58
60
}
59
61
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 ) ;
64
71
return id
65
72
}
66
73
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
+
67
87
const callHostFunction = ( host_func_id : number , args : any [ ] ) => {
68
88
if ( ! this . instance )
69
89
throw new Error ( "WebAssembly instance is not set yet" ) ;
@@ -79,7 +99,7 @@ export class SwiftRuntime {
79
99
writeUint32 ( base + 8 , value . payload2 )
80
100
}
81
101
let output : any ;
82
- const callback_func_ref = allocValue ( function ( result : any ) {
102
+ const callback_func_ref = allocHeap ( function ( result : any ) {
83
103
output = result
84
104
} )
85
105
exports . swjs_call_host_function ( host_func_id , argv , argc , callback_func_ref )
@@ -137,7 +157,7 @@ export class SwiftRuntime {
137
157
return readString ( payload1 , payload2 )
138
158
}
139
159
case JavaScriptValueKind . Object : {
140
- return this . _heapValues [ payload1 ]
160
+ return referenceHeap ( payload1 )
141
161
}
142
162
case JavaScriptValueKind . Null : {
143
163
return null
@@ -146,7 +166,7 @@ export class SwiftRuntime {
146
166
return undefined
147
167
}
148
168
case JavaScriptValueKind . Function : {
149
- return this . _heapValues [ payload1 ]
169
+ return referenceHeap ( payload1 )
150
170
}
151
171
default :
152
172
throw new Error ( `Type kind "${ kind } " is not supported` )
@@ -179,7 +199,7 @@ export class SwiftRuntime {
179
199
case "string" : {
180
200
return {
181
201
kind : JavaScriptValueKind . String ,
182
- payload1 : allocValue ( value ) ,
202
+ payload1 : allocHeap ( value ) ,
183
203
payload2 : value . length ,
184
204
}
185
205
}
@@ -193,14 +213,14 @@ export class SwiftRuntime {
193
213
case "object" : {
194
214
return {
195
215
kind : JavaScriptValueKind . Object ,
196
- payload1 : allocValue ( value ) ,
216
+ payload1 : allocHeap ( value ) ,
197
217
payload2 : 0 ,
198
218
}
199
219
}
200
220
case "function" : {
201
221
return {
202
222
kind : JavaScriptValueKind . Function ,
203
- payload1 : allocValue ( value ) ,
223
+ payload1 : allocHeap ( value ) ,
204
224
payload2 : 0 ,
205
225
}
206
226
}
@@ -230,15 +250,15 @@ export class SwiftRuntime {
230
250
kind : JavaScriptValueKind ,
231
251
payload1 : number , payload2 : number
232
252
) => {
233
- const obj = this . _heapValues [ ref ] ;
253
+ const obj = referenceHeap ( ref ) ;
234
254
Reflect . set ( obj , readString ( name , length ) , decodeValue ( kind , payload1 , payload2 ) )
235
255
} ,
236
256
swjs_get_prop : (
237
257
ref : ref , name : pointer , length : number ,
238
258
kind_ptr : pointer ,
239
259
payload1_ptr : pointer , payload2_ptr : pointer
240
260
) => {
241
- const obj = this . _heapValues [ ref ] ;
261
+ const obj = referenceHeap ( ref ) ;
242
262
const result = Reflect . get ( obj , readString ( name , length ) ) ;
243
263
const { kind, payload1, payload2 } = encodeValue ( result ) ;
244
264
writeUint32 ( kind_ptr , kind ) ;
@@ -250,31 +270,31 @@ export class SwiftRuntime {
250
270
kind : JavaScriptValueKind ,
251
271
payload1 : number , payload2 : number
252
272
) => {
253
- const obj = this . _heapValues [ ref ] ;
273
+ const obj = referenceHeap ( ref ) ;
254
274
Reflect . set ( obj , index , decodeValue ( kind , payload1 , payload2 ) )
255
275
} ,
256
276
swjs_get_subscript : (
257
277
ref : ref , index : number ,
258
278
kind_ptr : pointer ,
259
279
payload1_ptr : pointer , payload2_ptr : pointer
260
280
) => {
261
- const obj = this . _heapValues [ ref ] ;
281
+ const obj = referenceHeap ( ref ) ;
262
282
const result = Reflect . get ( obj , index ) ;
263
283
const { kind, payload1, payload2 } = encodeValue ( result ) ;
264
284
writeUint32 ( kind_ptr , kind ) ;
265
285
writeUint32 ( payload1_ptr , payload1 ) ;
266
286
writeUint32 ( payload2_ptr , payload2 ) ;
267
287
} ,
268
288
swjs_load_string : ( ref : ref , buffer : pointer ) => {
269
- const string = this . _heapValues [ ref ] ;
289
+ const string = referenceHeap ( ref ) ;
270
290
writeString ( buffer , string ) ;
271
291
} ,
272
292
swjs_call_function : (
273
293
ref : ref , argv : pointer , argc : number ,
274
294
kind_ptr : pointer ,
275
295
payload1_ptr : pointer , payload2_ptr : pointer
276
296
) => {
277
- const func = this . _heapValues [ ref ]
297
+ const func = referenceHeap ( ref )
278
298
const result = Reflect . apply ( func , undefined , decodeValues ( argv , argc ) )
279
299
const { kind, payload1, payload2 } = encodeValue ( result ) ;
280
300
writeUint32 ( kind_ptr , kind ) ;
@@ -287,8 +307,8 @@ export class SwiftRuntime {
287
307
kind_ptr : pointer ,
288
308
payload1_ptr : pointer , payload2_ptr : pointer
289
309
) => {
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 )
292
312
const result = Reflect . apply ( func , obj , decodeValues ( argv , argc ) )
293
313
const { kind, payload1, payload2 } = encodeValue ( result ) ;
294
314
writeUint32 ( kind_ptr , kind ) ;
@@ -299,7 +319,7 @@ export class SwiftRuntime {
299
319
host_func_id : number ,
300
320
func_ref_ptr : pointer ,
301
321
) => {
302
- const func_ref = allocValue ( function ( ) {
322
+ const func_ref = allocHeap ( function ( ) {
303
323
return callHostFunction ( host_func_id , Array . prototype . slice . call ( arguments ) )
304
324
} )
305
325
writeUint32 ( func_ref_ptr , func_ref )
@@ -308,12 +328,15 @@ export class SwiftRuntime {
308
328
ref : ref , argv : pointer , argc : number ,
309
329
result_obj : pointer
310
330
) => {
311
- const obj = this . _heapValues [ ref ]
331
+ const obj = referenceHeap ( ref )
312
332
const result = Reflect . construct ( obj , decodeValues ( argv , argc ) )
313
333
if ( typeof result != "object" )
314
334
throw Error ( `Invalid result type of object constructor of "${ obj } ": "${ result } "` )
315
- writeUint32 ( result_obj , allocValue ( result ) ) ;
335
+ writeUint32 ( result_obj , allocHeap ( result ) ) ;
316
336
} ,
337
+ swjs_destroy_ref : ( ref : ref ) => {
338
+ freeHeap ( ref )
339
+ }
317
340
}
318
341
}
319
342
}
0 commit comments