|
202 | 202 | return;
|
203 | 203 | }
|
204 | 204 |
|
205 |
| - let ref = this._refs.get(v); |
206 |
| - if (ref === undefined) { |
207 |
| - ref = this._values.length; |
208 |
| - this._values.push(v); |
209 |
| - this._refs.set(v, ref); |
| 205 | + let id = this._ids.get(v); |
| 206 | + if (id === undefined) { |
| 207 | + id = this._idPool.pop(); |
| 208 | + if (id === undefined) { |
| 209 | + id = this._values.length; |
| 210 | + } |
| 211 | + this._values[id] = v; |
| 212 | + this._goRefCounts[id] = 0; |
| 213 | + this._ids.set(v, id); |
210 | 214 | }
|
211 |
| - let typeFlag = 0; |
| 215 | + this._goRefCounts[id]++; |
| 216 | + let typeFlag = 1; |
212 | 217 | switch (typeof v) {
|
213 | 218 | case "string":
|
214 |
| - typeFlag = 1; |
| 219 | + typeFlag = 2; |
215 | 220 | break;
|
216 | 221 | case "symbol":
|
217 |
| - typeFlag = 2; |
| 222 | + typeFlag = 3; |
218 | 223 | break;
|
219 | 224 | case "function":
|
220 |
| - typeFlag = 3; |
| 225 | + typeFlag = 4; |
221 | 226 | break;
|
222 | 227 | }
|
223 | 228 | mem().setUint32(addr + 4, nanHead | typeFlag, true);
|
224 |
| - mem().setUint32(addr, ref, true); |
| 229 | + mem().setUint32(addr, id, true); |
225 | 230 | }
|
226 | 231 |
|
227 | 232 | const loadSlice = (array, len, cap) => {
|
|
284 | 289 | setTimeout(this._inst.exports.go_scheduler, timeout);
|
285 | 290 | },
|
286 | 291 |
|
| 292 | + // func finalizeRef(v ref) |
| 293 | + "syscall/js.finalizeRef": (sp) => { |
| 294 | + // Note: TinyGo does not support finalizers so this should never be |
| 295 | + // called. |
| 296 | + console.error('syscall/js.finalizeRef not implemented'); |
| 297 | + }, |
| 298 | + |
287 | 299 | // func stringVal(value string) ref
|
288 | 300 | "syscall/js.stringVal": (ret_ptr, value_ptr, value_len) => {
|
289 | 301 | const s = loadString(value_ptr, value_len);
|
|
405 | 417 |
|
406 | 418 | async run(instance) {
|
407 | 419 | this._inst = instance;
|
408 |
| - this._values = [ // TODO: garbage collection |
| 420 | + this._values = [ // JS values that Go currently has references to, indexed by reference id |
409 | 421 | NaN,
|
410 | 422 | 0,
|
411 | 423 | null,
|
|
414 | 426 | global,
|
415 | 427 | this,
|
416 | 428 | ];
|
417 |
| - this._refs = new Map(); |
418 |
| - this.exited = false; |
| 429 | + this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id |
| 430 | + this._ids = new Map(); // mapping from JS values to reference ids |
| 431 | + this._idPool = []; // unused ids that have been garbage collected |
| 432 | + this.exited = false; // whether the Go program has exited |
419 | 433 |
|
420 | 434 | const mem = new DataView(this._inst.exports.memory.buffer)
|
421 | 435 |
|
|
0 commit comments