| // Copyright (C) 2019 Ecma International. All rights reserved. |
| // This code is governed by the BSD license found in the LICENSE file. |
| /*--- |
| description: > |
| Collection of functions used to capture references cleanup from garbage collectors |
| features: [Symbol, async-functions] |
| flags: [non-deterministic] |
| features: [FinalizationRegistry] |
| defines: [asyncGC, asyncGCDeref, resolveAsyncGC] |
| ---*/ |
| |
| function asyncGC(...targets) { |
| var finalizationRegistry = new FinalizationRegistry(() => {}); |
| var length = targets.length; |
| |
| for (let target of targets) { |
| finalizationRegistry.register(target, 'target'); |
| target = null; |
| } |
| |
| targets = null; |
| |
| return Promise.resolve('tick').then(() => asyncGCDeref()).then(() => { |
| var names; |
| |
| // consume iterator to capture names |
| finalizationRegistry.cleanupSome(iter => { names = [...iter]; }); |
| |
| if (!names || names.length != length) { |
| throw asyncGC.notCollected; |
| } |
| }); |
| } |
| |
| asyncGC.notCollected = Symbol('Object was not collected'); |
| |
| async function asyncGCDeref() { |
| var trigger; |
| |
| // TODO: Remove this when $262.clearKeptObject becomes documented and required |
| if ($262.clearKeptObjects) { |
| trigger = $262.clearKeptObjects(); |
| } |
| |
| await $262.gc(); |
| |
| return Promise.resolve(trigger); |
| } |
| |
| function resolveAsyncGC(err) { |
| if (err === asyncGC.notCollected) { |
| // Do not fail as GC can't provide necessary resources. |
| $DONE(); |
| } |
| |
| $DONE(err); |
| } |