// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --harmony-weak-refs (function TestConstructFinalizationGroup() { let fg = new FinalizationGroup(() => {}); assertEquals(fg.toString(), "[object FinalizationGroup]"); assertNotSame(fg.__proto__, Object.prototype); assertSame(fg.__proto__.__proto__, Object.prototype); })(); (function TestFinalizationGroupConstructorCallAsFunction() { let caught = false; let message = ""; try { let f = FinalizationGroup(() => {}); } catch (e) { message = e.message; caught = true; } finally { assertTrue(caught); assertEquals(message, "Constructor FinalizationGroup requires 'new'"); } })(); (function TestConstructFinalizationGroupCleanupNotCallable() { let message = "FinalizationGroup: cleanup must be callable"; assertThrows(() => { let fg = new FinalizationGroup(); }, TypeError, message); assertThrows(() => { let fg = new FinalizationGroup(1); }, TypeError, message); assertThrows(() => { let fg = new FinalizationGroup(null); }, TypeError, message); })(); (function TestConstructFinalizationGroupWithCallableProxyAsCleanup() { let handler = {}; let obj = () => {}; let proxy = new Proxy(obj, handler); let fg = new FinalizationGroup(proxy); })(); (function TestConstructFinalizationGroupWithNonCallableProxyAsCleanup() { let message = "FinalizationGroup: cleanup must be callable"; let handler = {}; let obj = {}; let proxy = new Proxy(obj, handler); assertThrows(() => { let fg = new FinalizationGroup(proxy); }, TypeError, message); })(); (function TestRegisterWithNonObjectTarget() { let fg = new FinalizationGroup(() => {}); let message = "FinalizationGroup.prototype.register: target must be an object"; assertThrows(() => fg.register(1, "holdings"), TypeError, message); assertThrows(() => fg.register(false, "holdings"), TypeError, message); assertThrows(() => fg.register("foo", "holdings"), TypeError, message); assertThrows(() => fg.register(Symbol(), "holdings"), TypeError, message); assertThrows(() => fg.register(null, "holdings"), TypeError, message); assertThrows(() => fg.register(undefined, "holdings"), TypeError, message); })(); (function TestRegisterWithProxy() { let handler = {}; let obj = {}; let proxy = new Proxy(obj, handler); let fg = new FinalizationGroup(() => {}); fg.register(proxy); })(); (function TestRegisterTargetAndHoldingsSameValue() { let fg = new FinalizationGroup(() => {}); let obj = {a: 1}; // SameValue(target, holdings) not ok assertThrows(() => fg.register(obj, obj), TypeError, "FinalizationGroup.prototype.register: target and holdings must not be same"); let holdings = {a: 1}; fg.register(obj, holdings); })(); (function TestRegisterWithoutFinalizationGroup() { assertThrows(() => FinalizationGroup.prototype.register.call({}, {}, "holdings"), TypeError); // Does not throw: let fg = new FinalizationGroup(() => {}); FinalizationGroup.prototype.register.call(fg, {}, "holdings"); })(); (function TestUnregisterWithNonExistentKey() { let fg = new FinalizationGroup(() => {}); let success = fg.unregister({"k": "whatever"}); assertFalse(success); })(); (function TestUnregisterWithNonFinalizationGroup() { assertThrows(() => FinalizationGroup.prototype.unregister.call({}, {}), TypeError); })(); (function TestUnregisterWithNonObjectUnregisterToken() { let fg = new FinalizationGroup(() => {}); assertThrows(() => fg.unregister(1), TypeError); assertThrows(() => fg.unregister(1n), TypeError); assertThrows(() => fg.unregister('one'), TypeError); assertThrows(() => fg.unregister(Symbol()), TypeError); assertThrows(() => fg.unregister(true), TypeError); assertThrows(() => fg.unregister(false), TypeError); assertThrows(() => fg.unregister(undefined), TypeError); assertThrows(() => fg.unregister(null), TypeError); })(); (function TestWeakRefConstructor() { let wr = new WeakRef({}); assertEquals(wr.toString(), "[object WeakRef]"); assertNotSame(wr.__proto__, Object.prototype); let deref_desc = Object.getOwnPropertyDescriptor(wr.__proto__, "deref"); assertEquals(true, deref_desc.configurable); assertEquals(false, deref_desc.enumerable); assertEquals("function", typeof deref_desc.value); })(); (function TestWeakRefConstructorWithNonObject() { let message = "WeakRef: target must be an object"; assertThrows(() => new WeakRef(), TypeError, message); assertThrows(() => new WeakRef(1), TypeError, message); assertThrows(() => new WeakRef(false), TypeError, message); assertThrows(() => new WeakRef("foo"), TypeError, message); assertThrows(() => new WeakRef(Symbol()), TypeError, message); assertThrows(() => new WeakRef(null), TypeError, message); assertThrows(() => new WeakRef(undefined), TypeError, message); })(); (function TestWeakRefConstructorCallAsFunction() { let caught = false; let message = ""; try { let f = WeakRef({}); } catch (e) { message = e.message; caught = true; } finally { assertTrue(caught); assertEquals(message, "Constructor WeakRef requires 'new'"); } })(); (function TestWeakRefWithProxy() { let handler = {}; let obj = {}; let proxy = new Proxy(obj, handler); let wr = new WeakRef(proxy); })(); (function TestCleanupSomeWithoutFinalizationGroup() { assertThrows(() => FinalizationGroup.prototype.cleanupSome.call({}), TypeError); // Does not throw: let fg = new FinalizationGroup(() => {}); let rv = FinalizationGroup.prototype.cleanupSome.call(fg); assertEquals(undefined, rv); })(); (function TestCleanupSomeWithNonCallableCallback() { let fg = new FinalizationGroup(() => {}); assertThrows(() => fg.cleanupSome(1), TypeError); assertThrows(() => fg.cleanupSome(1n), TypeError); assertThrows(() => fg.cleanupSome(Symbol()), TypeError); assertThrows(() => fg.cleanupSome({}), TypeError); assertThrows(() => fg.cleanupSome('foo'), TypeError); assertThrows(() => fg.cleanupSome(true), TypeError); assertThrows(() => fg.cleanupSome(false), TypeError); assertThrows(() => fg.cleanupSome(null), TypeError); })();