diff --git a/js/public/Class.h b/js/public/Class.h index a2aa8bb4d36a9..abc7260949ea6 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -700,7 +700,7 @@ static const uint32_t JSCLASS_FOREGROUND_FINALIZE = // application. static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5; static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT = - JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 26; + JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 25; static constexpr uint32_t JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(uint32_t n) { return JSCLASS_IS_GLOBAL | diff --git a/js/src/builtin/FinalizationRegistryObject.cpp b/js/src/builtin/FinalizationRegistryObject.cpp index 04e119f7c3f5b..bc9e660c3f33e 100644 --- a/js/src/builtin/FinalizationRegistryObject.cpp +++ b/js/src/builtin/FinalizationRegistryObject.cpp @@ -326,7 +326,6 @@ bool FinalizationRegistryObject::construct(JSContext* cx, unsigned argc, recordsToBeCleanedUp.release(), MemoryUse::FinalizationRegistryRecordVector); registry->initReservedSlot(IsQueuedForCleanupSlot, BooleanValue(false)); - registry->initReservedSlot(IsCleanupJobActiveSlot, BooleanValue(false)); if (!cx->runtime()->gc.addFinalizationRegistry(cx, registry)) { return false; @@ -439,10 +438,6 @@ bool FinalizationRegistryObject::isQueuedForCleanup() const { return getReservedSlot(IsQueuedForCleanupSlot).toBoolean(); } -bool FinalizationRegistryObject::isCleanupJobActive() const { - return getReservedSlot(IsCleanupJobActiveSlot).toBoolean(); -} - void FinalizationRegistryObject::queueRecordToBeCleanedUp( FinalizationRecordObject* record) { AutoEnterOOMUnsafeRegion oomUnsafe; @@ -456,11 +451,6 @@ void FinalizationRegistryObject::setQueuedForCleanup(bool value) { setReservedSlot(IsQueuedForCleanupSlot, BooleanValue(value)); } -void FinalizationRegistryObject::setCleanupJobActive(bool value) { - MOZ_ASSERT(value != isCleanupJobActive()); - setReservedSlot(IsCleanupJobActiveSlot, BooleanValue(value)); -} - // FinalizationRegistry.prototype.register(target, heldValue [, unregisterToken // ]) // https://tc39.es/proposal-weakrefs/#sec-finalization-registry.prototype.register @@ -705,11 +695,7 @@ bool FinalizationRegistryObject::cleanupSome(JSContext* cx, unsigned argc, CallArgs args = CallArgsFromVp(argc, vp); // 1. Let finalizationRegistry be the this value. - // 2. If Type(finalizationRegistry) is not Object, throw a TypeError - // exception. - // 3. If finalizationRegistry does not have [[Cells]] and - // [[IsFinalizationRegistryCleanupJobActive]] internal slots, throw a - // TypeError exception. + // 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]). if (!args.thisv().isObject() || !args.thisv().toObject().is()) { JS_ReportErrorNumberASCII( @@ -718,17 +704,10 @@ bool FinalizationRegistryObject::cleanupSome(JSContext* cx, unsigned argc, return false; } - // 4. If finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] is - // true, throw a TypeError exception. RootedFinalizationRegistryObject registry( cx, &args.thisv().toObject().as()); - if (registry->isCleanupJobActive()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_BAD_CLEANUP_STATE); - return false; - } - // 5. If callback is not undefined and IsCallable(callback) is false, throw a + // 3. If callback is not undefined and IsCallable(callback) is false, throw a // TypeError exception. RootedObject cleanupCallback(cx); if (!args.get(0).isUndefined()) { @@ -746,24 +725,6 @@ bool FinalizationRegistryObject::cleanupSome(JSContext* cx, unsigned argc, return true; } -/* static */ -bool FinalizationRegistryObject::hasRegisteredRecordsToBeCleanedUp( - HandleFinalizationRegistryObject registry) { - FinalizationRecordVector* records = registry->recordsToBeCleanedUp(); - size_t initialLength = records->length(); - if (initialLength == 0) { - return false; - } - - for (FinalizationRecordObject* record : *records) { - if (record->isActive()) { - return true; - } - } - - return false; -} - // CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] ) // https://tc39.es/proposal-weakrefs/#sec-cleanup-finalization-registry /* static */ @@ -772,20 +733,7 @@ bool FinalizationRegistryObject::cleanupQueuedRecords( HandleObject callbackArg) { MOZ_ASSERT(cx->compartment() == registry->compartment()); - // 2. If CheckForEmptyCells(finalizationRegistry) is false, return. - if (!hasRegisteredRecordsToBeCleanedUp(registry)) { - return true; - } - - // 3. Let iterator be - // !CreateFinalizationRegistryCleanupIterator(finalizationRegistry). - Rooted iterator( - cx, FinalizationIteratorObject::create(cx, registry)); - if (!iterator) { - return false; - } - - // 4. If callback is undefined, set callback to + // 2. If callback is undefined, set callback to // finalizationRegistry.[[CleanupCallback]]. RootedValue callback(cx); if (callbackArg) { @@ -796,193 +744,34 @@ bool FinalizationRegistryObject::cleanupQueuedRecords( callback.setObject(*cleanupCallback); } - // 5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to - // true. - registry->setCleanupJobActive(true); - - FinalizationRecordVector* records = registry->recordsToBeCleanedUp(); -#ifdef DEBUG - size_t initialLength = records->length(); -#endif - - // 6. Let result be Call(callback, undefined, iterator). - RootedValue iteratorVal(cx, ObjectValue(*iterator)); - RootedValue rval(cx); - bool ok = Call(cx, callback, UndefinedHandleValue, iteratorVal, &rval); - - // Remove records that were iterated over. - size_t index = iterator->index(); - MOZ_ASSERT(index <= records->length()); - MOZ_ASSERT(initialLength <= records->length()); - if (index > 0) { - records->erase(records->begin(), records->begin() + index); - } - - // 7. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to - // false. - registry->setCleanupJobActive(false); - - // 8. Set iterator.[[FinalizationRegistry]] to empty. - iterator->clearFinalizationRegistry(); - - return ok; -} - -/////////////////////////////////////////////////////////////////////////// -// FinalizationIteratorObject - -const JSClass FinalizationIteratorObject::class_ = { - "FinalizationRegistryCleanupIterator", - JSCLASS_HAS_RESERVED_SLOTS(SlotCount), JS_NULL_CLASS_OPS, - JS_NULL_CLASS_SPEC}; - -const JSFunctionSpec FinalizationIteratorObject::methods_[] = { - JS_FN(js_next_str, next, 0, 0), JS_FS_END}; - -const JSPropertySpec FinalizationIteratorObject::properties_[] = { - JS_STRING_SYM_PS(toStringTag, "FinalizationRegistry Cleanup Iterator", - JSPROP_READONLY), - JS_PS_END}; - -/* static */ -bool GlobalObject::initFinalizationIteratorProto(JSContext* cx, - Handle global) { - Rooted base( - cx, GlobalObject::getOrCreateIteratorPrototype(cx, global)); - if (!base) { - return false; - } - RootedPlainObject proto( - cx, GlobalObject::createBlankPrototypeInheriting(cx, base)); - if (!proto) { - return false; - } - if (!JS_DefineFunctions(cx, proto, FinalizationIteratorObject::methods_) || - !JS_DefineProperties(cx, proto, - FinalizationIteratorObject::properties_)) { - return false; - } - global->setReservedSlot(FINALIZATION_ITERATOR_PROTO, ObjectValue(*proto)); - return true; -} - -/* static */ FinalizationIteratorObject* FinalizationIteratorObject::create( - JSContext* cx, HandleFinalizationRegistryObject registry) { - MOZ_ASSERT(registry); - - RootedObject proto(cx, GlobalObject::getOrCreateFinalizationIteratorPrototype( - cx, cx->global())); - if (!proto) { - return nullptr; - } - - FinalizationIteratorObject* iterator = - NewObjectWithGivenProto(cx, proto); - if (!iterator) { - return nullptr; - } - - iterator->initReservedSlot(FinalizationRegistrySlot, ObjectValue(*registry)); - iterator->initReservedSlot(IndexSlot, Int32Value(0)); - - return iterator; -} - -FinalizationRegistryObject* FinalizationIteratorObject::finalizationRegistry() - const { - Value value = getReservedSlot(FinalizationRegistrySlot); - if (value.isUndefined()) { - return nullptr; - } - return &value.toObject().as(); -} - -size_t FinalizationIteratorObject::index() const { - int32_t i = getReservedSlot(IndexSlot).toInt32(); - MOZ_ASSERT(i >= 0); - return size_t(i); -} - -void FinalizationIteratorObject::setIndex(size_t i) { - MOZ_ASSERT(i <= INT32_MAX); - setReservedSlot(IndexSlot, Int32Value(int32_t(i))); -} - -void FinalizationIteratorObject::clearFinalizationRegistry() { - MOZ_ASSERT(finalizationRegistry()); - setReservedSlot(FinalizationRegistrySlot, UndefinedValue()); -} - -// %FinalizationRegistryCleanupIteratorPrototype%.next() -// https://tc39.es/proposal-weakrefs/#sec-%finalizationregistrycleanupiterator%.next -/* static */ -bool FinalizationIteratorObject::next(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - // 1. Let iterator be the this value. - // 2. If Type(iterator) is not Object, throw a TypeError exception. - // 3. If iterator does not have a [[FinalizationRegistry]] internal slot, - // throw a TypeError exception. - if (!args.thisv().isObject() || - !args.thisv().toObject().is()) { - JS_ReportErrorNumberASCII( - cx, GetErrorMessage, nullptr, JSMSG_NOT_A_FINALIZATION_ITERATOR, - "Receiver of FinalizationRegistryCleanupIterator.next call"); - return false; - } - - RootedFinalizationIteratorObject iterator( - cx, &args.thisv().toObject().as()); - - // 4. If iterator.[[FinalizationRegistry]] is empty, throw a TypeError - // exception. - // 5. Let finalizationRegistry be iterator.[[FinalizationRegistry]]. - RootedFinalizationRegistryObject registry(cx, - iterator->finalizationRegistry()); - if (!registry) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_STALE_FINALIZATION_REGISTRY_ITERATOR); - return false; - } - - // 8. If finalizationRegistry.[[Cells]] contains a Record cell such that - // cell.[[Target]] is empty, + // 3. While finalizationRegistry.[[Cells]] contains a Record cell such that + // cell.[[WeakRefTarget]] is empty, then an implementation may perform the + // following steps, // a. Choose any such cell. // b. Remove cell from finalizationRegistry.[[Cells]]. - // c. Return CreateIterResultObject(cell.[[HeldValue]], false). - FinalizationRecordVector* records = registry->recordsToBeCleanedUp(); - size_t index = iterator->index(); - MOZ_ASSERT(index <= records->length()); + // c. Perform ? Call(callback, undefined, « cell.[[HeldValue]] »). - // Advance until we find a record that hasn't been unregistered. - while (index < records->length() && index < INT32_MAX && - !(*records)[index]->isActive()) { - index++; - iterator->setIndex(index); - } + RootedValue heldValue(cx); + RootedValue rval(cx); + FinalizationRecordVector* records = registry->recordsToBeCleanedUp(); + FinalizationRecordSet* activeRecords = registry->activeRecords(); + while (!records->empty()) { + FinalizationRecordObject* record = records->popCopy(); - if (index < records->length() && index < INT32_MAX) { - RootedFinalizationRecordObject record(cx, (*records)[index]); - RootedValue heldValue(cx, record->heldValue()); - PlainObject* result = CreateIterResultObject(cx, heldValue, false); - if (!result) { - return false; + // Skip over records that have been unregistered. + if (!record->isActive()) { + continue; } - registry->activeRecords()->remove(record); - record->clear(); - iterator->setIndex(index + 1); + heldValue.set(record->heldValue()); - args.rval().setObject(*result); - return true; - } + activeRecords->remove(record); + record->clear(); - // 9. Otherwise, return CreateIterResultObject(undefined, true). - PlainObject* result = CreateIterResultObject(cx, UndefinedHandleValue, true); - if (!result) { - return false; + if (!Call(cx, callback, UndefinedHandleValue, heldValue, &rval)) { + return false; + } } - args.rval().setObject(*result); return true; } diff --git a/js/src/builtin/FinalizationRegistryObject.h b/js/src/builtin/FinalizationRegistryObject.h index 926862a6cecb3..b9dbc05992955 100644 --- a/js/src/builtin/FinalizationRegistryObject.h +++ b/js/src/builtin/FinalizationRegistryObject.h @@ -181,7 +181,6 @@ class FinalizationRegistryObject : public NativeObject { ActiveRecords, RecordsToBeCleanedUpSlot, IsQueuedForCleanupSlot, - IsCleanupJobActiveSlot, SlotCount }; @@ -194,11 +193,9 @@ class FinalizationRegistryObject : public NativeObject { FinalizationRecordSet* activeRecords() const; FinalizationRecordVector* recordsToBeCleanedUp() const; bool isQueuedForCleanup() const; - bool isCleanupJobActive() const; void queueRecordToBeCleanedUp(FinalizationRecordObject* record); void setQueuedForCleanup(bool value); - void setCleanupJobActive(bool value); void sweep(); @@ -227,9 +224,6 @@ class FinalizationRegistryObject : public NativeObject { static void trace(JSTracer* trc, JSObject* obj); static void finalize(JSFreeOp* fop, JSObject* obj); - - static bool hasRegisteredRecordsToBeCleanedUp( - HandleFinalizationRegistryObject registry); }; // An iterator over a finalization registry's queued held values. In the spec diff --git a/js/src/jit-test/tests/gc/bug-1620196.js b/js/src/jit-test/tests/gc/bug-1620196.js index 2d145a1870929..79f98e073e894 100644 --- a/js/src/jit-test/tests/gc/bug-1620196.js +++ b/js/src/jit-test/tests/gc/bug-1620196.js @@ -2,8 +2,8 @@ gczeal(4); let heldValues = []; -registry = new FinalizationRegistry(iterator => { - heldValues.push(...iterator); +registry = new FinalizationRegistry(value => { + heldValues.push(value); }); registry.register({}, 42); gc(); diff --git a/js/src/jit-test/tests/gc/bug1600488-1.js b/js/src/jit-test/tests/gc/bug1600488-1.js index 7827ec5baca03..b15bb2f2912c0 100644 --- a/js/src/jit-test/tests/gc/bug1600488-1.js +++ b/js/src/jit-test/tests/gc/bug1600488-1.js @@ -1,9 +1,9 @@ // |jit-test| --enable-weak-refs const token = {}; -let iterated; -const finalizationRegistry = new FinalizationRegistry(items => { - iterated = items.next().value; +let cleanedUpValue; +const finalizationRegistry = new FinalizationRegistry(value => { + cleanedUpValue = value; }); { let object = {}; @@ -12,5 +12,5 @@ const finalizationRegistry = new FinalizationRegistry(items => { } gc(); finalizationRegistry.cleanupSome(); -assertEq(iterated, token); +assertEq(cleanedUpValue, token); assertEq(finalizationRegistry.unregister(token), false); diff --git a/js/src/jit-test/tests/gc/finalizationRegistry-ccw.js b/js/src/jit-test/tests/gc/finalizationRegistry-ccw.js index 12517b132b384..da4faffc40375 100644 --- a/js/src/jit-test/tests/gc/finalizationRegistry-ccw.js +++ b/js/src/jit-test/tests/gc/finalizationRegistry-ccw.js @@ -11,8 +11,8 @@ function ccwToObject() { } function newRegistry() { - return new FinalizationRegistry(iterator => { - heldValues.push(...iterator); + return new FinalizationRegistry(value => { + heldValues.push(value); }); } @@ -20,7 +20,7 @@ function ccwToRegistry() { let global = newGlobal({newCompartment: true}); global.heldValues = heldValues; return global.eval( - `new FinalizationRegistry(iterator => heldValues.push(...iterator))`); + `new FinalizationRegistry(value => heldValues.push(value))`); } function incrementalGC() { diff --git a/js/src/jit-test/tests/gc/finalizationRegistry-cleanupSome-recursive.js b/js/src/jit-test/tests/gc/finalizationRegistry-cleanupSome-recursive.js new file mode 100644 index 0000000000000..2f38b8b899d79 --- /dev/null +++ b/js/src/jit-test/tests/gc/finalizationRegistry-cleanupSome-recursive.js @@ -0,0 +1,51 @@ +// |jit-test| --enable-weak-refs + +// Test trying to call cleanupSome recursively in callback. + +// 0: Initial state. +// 1: Attempt recursive calls. +// 2: After recursive calls. +let state = 0; + +let registry = new FinalizationRegistry(x => { + if (state === 0) { + state = 1; + try { + registry.cleanupSome(); + } catch (e) { + // Pass the test if any error was thrown. + return; + } finally { + state = 2; + } + throw new Error("expected stack overflow error"); + } + + if (state === 1) { + registry.cleanupSome(); + } +}); + +// Attempt to find the maximum supported stack depth. +function findStackSize(i) { + try { + return findStackSize(i + 1); + } catch { + return i; + } +} +const stackSize = findStackSize(0); + +// Multiply the calculated stack size by some factor just to be on the safe side. +const exceedStackDepthLimit = stackSize * 5; + +let values = []; +for (let i = 0; i < exceedStackDepthLimit; ++i) { + let v = {}; + registry.register(v, i); + values.push(v); +} +values.length = 0; + +gc(); +drainJobQueue(); diff --git a/js/src/jit-test/tests/gc/finalizationRegistry-gray.js b/js/src/jit-test/tests/gc/finalizationRegistry-gray.js index 1acdece8b6e5b..0746ad07cda42 100644 --- a/js/src/jit-test/tests/gc/finalizationRegistry-gray.js +++ b/js/src/jit-test/tests/gc/finalizationRegistry-gray.js @@ -2,7 +2,7 @@ // Test gray finalization registry is correctly barrired. target = {}; -registry = new FinalizationRegistry(iterator => undefined); +registry = new FinalizationRegistry(value => undefined); registry.register(target, 1); grayRoot()[0] = registry; registry = undefined; diff --git a/js/src/jit-test/tests/gc/finalizationRegistry.js b/js/src/jit-test/tests/gc/finalizationRegistry.js index c4af5a3c4e5e3..740c102ec5dd8 100644 --- a/js/src/jit-test/tests/gc/finalizationRegistry.js +++ b/js/src/jit-test/tests/gc/finalizationRegistry.js @@ -61,36 +61,9 @@ let registry = new FinalizationRegistry(x => 0); assertEq(Object.getPrototypeOf(registry), proto); assertEq(Object.getOwnPropertyNames(registry).length, 0); -// Get a cleanup iterator. -let iterator; -registry = new FinalizationRegistry(it => iterator = it); -registry.register({}, 0); -gc(); -drainJobQueue(); -assertEq(typeof registry, 'object'); -assertEq(typeof iterator, 'object'); - -// 3.5.2 The %FinalizationRegistryCleanupIteratorPrototype% Object -let arrayIterator = [][Symbol.iterator](); -let iteratorProto = arrayIterator.__proto__.__proto__; -proto = iterator.__proto__; -assertEq(typeof proto, "object"); -assertEq(proto.__proto__, iteratorProto); - -// 3.5.2.1 %FinalizationRegistryCleanupIteratorPrototype%.next() -assertEq(proto.hasOwnProperty("next"), true); -assertEq(typeof proto.next, "function"); - -// 3.5.2.2 %FinalizationRegistryCleanupIteratorPrototype% [ @@toStringTag ] -assertEq(proto[Symbol.toStringTag], "FinalizationRegistry Cleanup Iterator"); -checkPropertyDescriptor(proto, Symbol.toStringTag, false, false, true); - -// 3.5.3 Properties of FinalizationRegistry Cleanup Iterator Instances -assertEq(Object.getOwnPropertyNames(iterator).length, 0); - let heldValues = []; -registry = new FinalizationRegistry(iterator => { - heldValues.push(...iterator); +registry = new FinalizationRegistry(value => { + heldValues.push(value); }); // Test a single target. @@ -117,8 +90,8 @@ for (let i = 0; i < 100; i++) { // Test a single object in multiple registries heldValues = []; let heldValues2 = []; -let registry2 = new FinalizationRegistry(iterator => { - heldValues2.push(...iterator); +let registry2 = new FinalizationRegistry(value => { + heldValues2.push(value); }); { let object = {}; @@ -196,8 +169,8 @@ class MyRegistry extends FinalizationRegistry { super(callback); } } -let r2 = new MyRegistry(iterator => { - heldValues.push(...iterator); +let r2 = new MyRegistry(value => { + heldValues.push(value); }); heldValues = []; r2.register({}, 42); @@ -206,26 +179,9 @@ drainJobQueue(); assertEq(heldValues.length, 1); assertEq(heldValues[0], 42); -// Test trying to use iterator after the callback. -iterator = undefined; -let r3 = new FinalizationRegistry(i => iterator = i); -r3.register({}, 1); -gc(); -drainJobQueue(); -assertEq(typeof iterator, 'object'); -assertThrowsTypeError(() => iterator.next()); - -// Test trying to use the wrong iterator inside the callback. -let r4 = new FinalizationRegistry(x => { - assertThrowsTypeError(() => iterator.next()); -}); -r4.register({}, 1); -gc(); -drainJobQueue(); - // Test cleanupSome. heldValues = []; -let r5 = new FinalizationRegistry(i => heldValues = [...i]); +let r5 = new FinalizationRegistry(v => heldValues.push(v)); r5.register({}, 1); r5.register({}, 2); r5.register({}, 3); @@ -239,15 +195,29 @@ assertEq(heldValues[2], 3); // Test trying to call cleanupSome in callback. let r6 = new FinalizationRegistry(x => { - assertThrowsTypeError(() => r6.cleanupSome()); + r6.cleanupSome(); }); r6.register({}, 1); gc(); drainJobQueue(); +// Test trying to call cleanupSome in callback with multiple values. +let callbackCounter7 = 0; +let r7 = new FinalizationRegistry(x => { + callbackCounter7++; + r7.cleanupSome(); +}); +r7.register({}, 1); +r7.register({}, 2); +r7.register({}, 3); +r7.register({}, 4); +gc(); +drainJobQueue(); +assertEq(callbackCounter7, 4); + // Test that targets don't keep the finalization registry alive. let target = {}; -registry = new FinalizationRegistry(iterator => undefined); +registry = new FinalizationRegistry(value => undefined); registry.register(target, 1); let weakRef = new WeakRef(registry); registry = undefined; @@ -259,7 +229,7 @@ assertEq(typeof target, 'object'); // Test that targets don't keep the finalization registry alive when also // used as the unregister token. -registry = new FinalizationRegistry(iterator => undefined); +registry = new FinalizationRegistry(value => undefined); registry.register(target, 1, target); weakRef = new WeakRef(registry); registry = undefined; @@ -271,8 +241,8 @@ assertEq(typeof target, 'object'); // Test that cleanup doesn't happen if the finalization registry dies. heldValues = []; -new FinalizationRegistry(iterator => { - heldValues.push(...iterator); +new FinalizationRegistry(value => { + heldValues.push(value); }).register({}, 1); gc(); drainJobQueue(); diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list index 1ae5295bd5f38..afdd45ab53927 100644 --- a/js/src/tests/jstests.list +++ b/js/src/tests/jstests.list @@ -412,14 +412,6 @@ skip script test262/intl402/ListFormat/constructor/constructor/proto-from-ctor-r # https://bugzilla.mozilla.org/show_bug.cgi?id=1362154 skip script test262/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js -# https://github.com/tc39/proposal-weakrefs/pull/187 -# https://bugzilla.mozilla.org/show_bug.cgi?id=1629796 -skip script test262/built-ins/FinalizationRegistry/gc-has-one-chance-to-call-cleanupCallback.js -skip script test262/built-ins/FinalizationRegistry/prototype/cleanupSome/holdings-multiple-values.js -skip script test262/built-ins/FinalizationRegistry/prototype/cleanupSome/cleanup-prevented-with-reference.js -skip script test262/built-ins/FinalizationRegistry/prototype/cleanupSome/reentrancy.js -skip script test262/built-ins/FinalizationRegistry/prototype/unregister/unregister-cleaned-up-cell.js - # Depends upon the SharedArrayBuffer constructor being defined as a global # property -- and right now, it's only defined for cross-site-isolated pages # that request it using COOP/COEP. diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 35a0b6872cce5..b708c67aa6f58 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -115,7 +115,6 @@ class GlobalObject : public NativeObject { IMPORT_ENTRY_PROTO, EXPORT_ENTRY_PROTO, REQUESTED_MODULE_PROTO, - FINALIZATION_ITERATOR_PROTO, REGEXP_STATICS, RUNTIME_CODEGEN_ENABLED, INTRINSICS, @@ -548,12 +547,6 @@ class GlobalObject : public NativeObject { return &global->getPrototype(JSProto_TypedArray).toObject(); } - static JSObject* getOrCreateFinalizationIteratorPrototype( - JSContext* cx, Handle global) { - return getOrCreateObject(cx, global, FINALIZATION_ITERATOR_PROTO, - initFinalizationIteratorProto); - } - private: using ObjectInitOp = bool (*)(JSContext*, Handle); @@ -853,10 +846,6 @@ class GlobalObject : public NativeObject { static bool initTypedObjectModule(JSContext* cx, Handle global); - // Implemented in builtin/FinalizationRegistry.cpp - static bool initFinalizationIteratorProto(JSContext* cx, - Handle global); - static bool initStandardClasses(JSContext* cx, Handle global); static bool initSelfHostingBuiltins(JSContext* cx, Handle global, diff --git a/js/xpconnect/tests/mochitest/finalizationRegistry_worker.js b/js/xpconnect/tests/mochitest/finalizationRegistry_worker.js index 8b2233c268930..d603cdab38002 100644 --- a/js/xpconnect/tests/mochitest/finalizationRegistry_worker.js +++ b/js/xpconnect/tests/mochitest/finalizationRegistry_worker.js @@ -19,27 +19,27 @@ onmessage = (event) => { function startTest() { // Registry with no registered objects. - let registry1 = new FinalizationRegistry(i => holdings1 = [...i]); + let registry1 = new FinalizationRegistry(v => { holdings1.push(v); }); // Registry with three registered objects. - let registry2 = new FinalizationRegistry(i => holdings2 = [...i]); + let registry2 = new FinalizationRegistry(v => { holdings2.push(v); }); registry2.register({}, 1); registry2.register({}, 2); registry2.register({}, 3); // Registry with registered object that is then unregistered. - let registry3 = new FinalizationRegistry(i => holdings3 = [...i]); + let registry3 = new FinalizationRegistry(v => { holdings3.push(v); }); let token3 = {} registry3.register({}, 1, token3); registry3.unregister(token3); // Registry with registered object that doesn't die. - let registry4 = new FinalizationRegistry(i => holdings4 = [...i]); + let registry4 = new FinalizationRegistry(v => { holdings4.push(v); }); let object4 = {}; registry4.register(object4, 1); // Registry observing cyclic JS data structure. - let registry5 = new FinalizationRegistry(i => holdings5 = [...i]); + let registry5 = new FinalizationRegistry(v => { holdings5.push(v); }); registry5.register(makeJSCycle(4), 5); const { gc } = getJSTestingFunctions(); diff --git a/js/xpconnect/tests/mochitest/test_finalizationRegistry.html b/js/xpconnect/tests/mochitest/test_finalizationRegistry.html index db9ddef14c902..dea4e39c4a4ac 100644 --- a/js/xpconnect/tests/mochitest/test_finalizationRegistry.html +++ b/js/xpconnect/tests/mochitest/test_finalizationRegistry.html @@ -12,35 +12,35 @@ // Registry with no registered objects. let holdings1 = []; - let registry1 = new FinalizationRegistry(i => holdings1 = [...i]); + let registry1 = new FinalizationRegistry(v => { holdings1.push(v); }); // Registry with three registered objects. let holdings2 = []; - let registry2 = new FinalizationRegistry(i => holdings2 = [...i]); + let registry2 = new FinalizationRegistry(v => { holdings2.push(v); }); registry2.register({}, 1); registry2.register({}, 2); registry2.register({}, 3); // Registry with registered object that is then unregistered. let holdings3 = []; - let registry3 = new FinalizationRegistry(i => holdings3 = [...i]); + let registry3 = new FinalizationRegistry(v => { holdings3.push(v); }); let token3 = {} registry3.register({}, 1, token3); registry3.unregister(token3); // Registry with registered object that doesn't die. let holdings4 = []; - let registry4 = new FinalizationRegistry(i => holdings4 = [...i]); + let registry4 = new FinalizationRegistry(v => { holdings4.push(v); }); registry4.register(object4, 1); // Registry observing cyclic JS data structure. let holdings5 = []; - let registry5 = new FinalizationRegistry(i => holdings5 = [...i]); + let registry5 = new FinalizationRegistry(v => { holdings5.push(v); }); registry5.register(makeJSCycle(4), 5); // Registry observing cyclic DOM/JS data structure. let holdings6 = []; - let registry6 = new FinalizationRegistry(i => holdings6 = [...i]); + let registry6 = new FinalizationRegistry(v => { holdings6.push(v); }); registry6.register(makeDOMCycle(4), 6); // Need to run full GC/CC/GC cycle to collect cyclic garbage through DOM