2018-10-11 12:56:18 +00:00
|
|
|
// 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.
|
|
|
|
|
2019-05-22 07:55:37 +00:00
|
|
|
#include "src/execution/isolate.h"
|
|
|
|
#include "src/execution/microtask-queue.h"
|
2019-05-22 12:44:24 +00:00
|
|
|
#include "src/handles/handles-inl.h"
|
2018-10-11 12:56:18 +00:00
|
|
|
#include "src/heap/factory-inl.h"
|
2018-12-17 13:22:01 +00:00
|
|
|
#include "src/objects/js-objects.h"
|
2018-11-23 10:52:27 +00:00
|
|
|
#include "src/objects/js-weak-refs-inl.h"
|
2018-10-11 12:56:18 +00:00
|
|
|
#include "test/cctest/cctest.h"
|
2018-12-17 13:22:01 +00:00
|
|
|
#include "test/cctest/heap/heap-utils.h"
|
2018-10-11 12:56:18 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2019-01-30 14:07:18 +00:00
|
|
|
namespace {
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> ConstructJSFinalizationRegistry(
|
|
|
|
Isolate* isolate) {
|
2018-10-11 12:56:18 +00:00
|
|
|
Factory* factory = isolate->factory();
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<String> finalization_registry_name =
|
2020-02-25 01:19:48 +00:00
|
|
|
factory->NewStringFromStaticChars("FinalizationRegistry");
|
2018-10-11 12:56:18 +00:00
|
|
|
Handle<Object> global =
|
|
|
|
handle(isolate->native_context()->global_object(), isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFunction> finalization_registry_fun = Handle<JSFunction>::cast(
|
|
|
|
Object::GetProperty(isolate, global, finalization_registry_name)
|
2018-10-11 12:56:18 +00:00
|
|
|
.ToHandleChecked());
|
2020-02-24 19:47:48 +00:00
|
|
|
auto finalization_registry = Handle<JSFinalizationRegistry>::cast(
|
|
|
|
JSObject::New(finalization_registry_fun, finalization_registry_fun,
|
2018-10-11 12:56:18 +00:00
|
|
|
Handle<AllocationSite>::null())
|
|
|
|
.ToHandleChecked());
|
|
|
|
#ifdef VERIFY_HEAP
|
2020-02-24 19:47:48 +00:00
|
|
|
finalization_registry->JSFinalizationRegistryVerify(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
#endif // VERIFY_HEAP
|
2020-02-24 19:47:48 +00:00
|
|
|
return finalization_registry;
|
2018-10-11 12:56:18 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<JSWeakRef> ConstructJSWeakRef(Handle<JSReceiver> target,
|
|
|
|
Isolate* isolate) {
|
2018-12-17 13:22:01 +00:00
|
|
|
Factory* factory = isolate->factory();
|
|
|
|
Handle<String> weak_ref_name = factory->WeakRef_string();
|
|
|
|
Handle<Object> global =
|
|
|
|
handle(isolate->native_context()->global_object(), isolate);
|
|
|
|
Handle<JSFunction> weak_ref_fun = Handle<JSFunction>::cast(
|
|
|
|
Object::GetProperty(isolate, global, weak_ref_name).ToHandleChecked());
|
|
|
|
auto weak_ref = Handle<JSWeakRef>::cast(
|
|
|
|
JSObject::New(weak_ref_fun, weak_ref_fun, Handle<AllocationSite>::null())
|
|
|
|
.ToHandleChecked());
|
|
|
|
weak_ref->set_target(*target);
|
|
|
|
#ifdef VERIFY_HEAP
|
|
|
|
weak_ref->JSWeakRefVerify(isolate);
|
|
|
|
#endif // VERIFY_HEAP
|
|
|
|
return weak_ref;
|
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<JSObject> CreateKey(const char* key_prop_value, Isolate* isolate) {
|
|
|
|
Factory* factory = isolate->factory();
|
|
|
|
Handle<String> key_string = factory->NewStringFromStaticChars("key_string");
|
|
|
|
Handle<JSObject> key =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
JSObject::AddProperty(isolate, key, key_string,
|
|
|
|
factory->NewStringFromAsciiChecked(key_prop_value),
|
|
|
|
NONE);
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> FinalizationRegistryRegister(
|
|
|
|
Handle<JSFinalizationRegistry> finalization_registry,
|
|
|
|
Handle<JSObject> target, Handle<Object> holdings, Handle<Object> key,
|
|
|
|
Isolate* isolate) {
|
|
|
|
JSFinalizationRegistry::Register(finalization_registry, target, holdings, key,
|
|
|
|
isolate);
|
|
|
|
CHECK(finalization_registry->active_cells().IsWeakCell());
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<WeakCell> weak_cell =
|
2020-02-24 19:47:48 +00:00
|
|
|
handle(WeakCell::cast(finalization_registry->active_cells()), isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
#ifdef VERIFY_HEAP
|
2019-01-30 12:06:32 +00:00
|
|
|
weak_cell->WeakCellVerify(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
#endif // VERIFY_HEAP
|
|
|
|
return weak_cell;
|
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> FinalizationRegistryRegister(
|
|
|
|
Handle<JSFinalizationRegistry> finalization_registry,
|
|
|
|
Handle<JSObject> target, Isolate* isolate) {
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
return FinalizationRegistryRegister(finalization_registry, target, undefined,
|
|
|
|
undefined, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NullifyWeakCell(Handle<WeakCell> weak_cell, Isolate* isolate) {
|
2018-12-25 00:19:47 +00:00
|
|
|
auto empty_func = [](HeapObject object, ObjectSlot slot, Object target) {};
|
2018-10-11 12:56:18 +00:00
|
|
|
weak_cell->Nullify(isolate, empty_func);
|
|
|
|
#ifdef VERIFY_HEAP
|
2019-01-30 12:06:32 +00:00
|
|
|
weak_cell->WeakCellVerify(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
#endif // VERIFY_HEAP
|
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Usage: VerifyWeakCellChain(isolate, list_head, n, cell1, cell2, ..., celln);
|
|
|
|
// verifies that list_head == cell1 and cell1, cell2, ..., celln. form a list.
|
|
|
|
void VerifyWeakCellChain(Isolate* isolate, Object list_head, int n_args, ...) {
|
|
|
|
CHECK_GE(n_args, 0);
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, n_args);
|
|
|
|
|
|
|
|
if (n_args == 0) {
|
|
|
|
// Verify empty list
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(list_head.IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
} else {
|
|
|
|
WeakCell current = WeakCell::cast(Object(va_arg(args, Address)));
|
|
|
|
CHECK_EQ(current, list_head);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(current.prev().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
for (int i = 1; i < n_args; i++) {
|
|
|
|
WeakCell next = WeakCell::cast(Object(va_arg(args, Address)));
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK_EQ(current.next(), next);
|
|
|
|
CHECK_EQ(next.prev(), current);
|
2019-01-30 12:06:32 +00:00
|
|
|
current = next;
|
|
|
|
}
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(current.next().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Like VerifyWeakCellChain but verifies the chain created with key_list_prev
|
|
|
|
// and key_list_next instead of prev and next.
|
2019-12-19 21:20:50 +00:00
|
|
|
void VerifyWeakCellKeyChain(Isolate* isolate, SimpleNumberDictionary key_map,
|
|
|
|
Object unregister_token, int n_args, ...) {
|
2019-01-30 12:06:32 +00:00
|
|
|
CHECK_GE(n_args, 0);
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, n_args);
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
Object hash = unregister_token.GetHash();
|
|
|
|
InternalIndex entry = InternalIndex::NotFound();
|
|
|
|
if (!hash.IsUndefined(isolate)) {
|
|
|
|
uint32_t key = Smi::ToInt(hash);
|
|
|
|
entry = key_map.FindEntry(isolate, key);
|
|
|
|
}
|
2019-01-30 12:06:32 +00:00
|
|
|
if (n_args == 0) {
|
|
|
|
// Verify empty list
|
2019-12-19 21:20:50 +00:00
|
|
|
CHECK(entry.is_not_found());
|
2019-01-30 12:06:32 +00:00
|
|
|
} else {
|
2019-12-19 21:20:50 +00:00
|
|
|
CHECK(entry.is_found());
|
2019-01-30 12:06:32 +00:00
|
|
|
WeakCell current = WeakCell::cast(Object(va_arg(args, Address)));
|
2019-12-19 21:20:50 +00:00
|
|
|
Object list_head = key_map.ValueAt(entry);
|
2019-01-30 12:06:32 +00:00
|
|
|
CHECK_EQ(current, list_head);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(current.key_list_prev().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
for (int i = 1; i < n_args; i++) {
|
|
|
|
WeakCell next = WeakCell::cast(Object(va_arg(args, Address)));
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK_EQ(current.key_list_next(), next);
|
|
|
|
CHECK_EQ(next.key_list_prev(), current);
|
2019-01-30 12:06:32 +00:00
|
|
|
current = next;
|
|
|
|
}
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(current.key_list_next().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
va_end(args);
|
2018-10-23 08:30:25 +00:00
|
|
|
}
|
|
|
|
|
2020-02-19 01:22:49 +00:00
|
|
|
Handle<JSWeakRef> MakeWeakRefAndKeepDuringJob(Isolate* isolate) {
|
|
|
|
HandleScope inner_scope(isolate);
|
|
|
|
|
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
Handle<JSWeakRef> inner_weak_ref = ConstructJSWeakRef(js_object, isolate);
|
|
|
|
isolate->heap()->KeepDuringJob(js_object);
|
|
|
|
|
|
|
|
return inner_scope.CloseAndEscape(inner_weak_ref);
|
|
|
|
}
|
|
|
|
|
2019-01-30 14:07:18 +00:00
|
|
|
} // namespace
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
TEST(TestRegister) {
|
2018-10-11 12:56:18 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Register a weak reference and verify internal data structures.
|
|
|
|
Handle<WeakCell> weak_cell1 =
|
2020-02-24 19:47:48 +00:00
|
|
|
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 1,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell1->key_list_prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell1->key_list_next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
// No key was used during registration, key-based map stays uninitialized.
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->key_map().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
// Register another weak reference and verify internal data structures.
|
|
|
|
Handle<WeakCell> weak_cell2 =
|
2020-02-24 19:47:48 +00:00
|
|
|
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 2,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2, *weak_cell1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell2->key_list_prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell2->key_list_next().IsUndefined(isolate));
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
|
|
|
|
CHECK(finalization_registry->key_map().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
TEST(TestRegisterWithKey) {
|
2018-10-11 12:56:18 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
|
|
|
Handle<JSObject> token2 = CreateKey("token2", isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
|
|
|
|
|
|
|
// Register a weak reference with a key and verify internal data structures.
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
|
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Register another weak reference with a different key and verify internal
|
|
|
|
// data structures.
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell2 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
|
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 1, *weak_cell2);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
// Register another weak reference with token1 and verify internal data
|
2019-01-30 12:06:32 +00:00
|
|
|
// structures.
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell3 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell3,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1);
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 1, *weak_cell2);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TestWeakCellNullify1) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
|
|
|
Handle<WeakCell> weak_cell1 =
|
2020-02-24 19:47:48 +00:00
|
|
|
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<WeakCell> weak_cell2 =
|
2020-02-24 19:47:48 +00:00
|
|
|
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
// Nullify the first WeakCell and verify internal data structures.
|
2018-10-11 12:56:18 +00:00
|
|
|
NullifyWeakCell(weak_cell1, isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK_EQ(finalization_registry->active_cells(), *weak_cell2);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell2->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell2->next().IsUndefined(isolate));
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell1->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell1->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Nullify the second WeakCell and verify internal data structures.
|
2018-10-11 12:56:18 +00:00
|
|
|
NullifyWeakCell(weak_cell2, isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->active_cells().IsUndefined(isolate));
|
|
|
|
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell2);
|
2018-10-11 12:56:18 +00:00
|
|
|
CHECK_EQ(weak_cell2->next(), *weak_cell1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell2->prev().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
CHECK_EQ(weak_cell1->prev(), *weak_cell2);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell1->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
TEST(TestWeakCellNullify2) {
|
2018-10-11 12:56:18 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<WeakCell> weak_cell1 =
|
2020-02-24 19:47:48 +00:00
|
|
|
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<WeakCell> weak_cell2 =
|
2020-02-24 19:47:48 +00:00
|
|
|
FinalizationRegistryRegister(finalization_registry, js_object, isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Like TestWeakCellNullify1 but nullify the WeakCells in opposite order.
|
2018-10-11 12:56:18 +00:00
|
|
|
NullifyWeakCell(weak_cell2, isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK_EQ(finalization_registry->active_cells(), *weak_cell1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell1->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell1->next().IsUndefined(isolate));
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell2);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell2->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell2->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
|
|
|
|
NullifyWeakCell(weak_cell1, isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->active_cells().IsUndefined(isolate));
|
|
|
|
CHECK_EQ(finalization_registry->cleared_cells(), *weak_cell1);
|
2018-10-11 12:56:18 +00:00
|
|
|
CHECK_EQ(weak_cell1->next(), *weak_cell2);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell1->prev().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
CHECK_EQ(weak_cell2->prev(), *weak_cell1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell2->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
TEST(TestJSFinalizationRegistryPopClearedCellHoldings1) {
|
2018-10-11 12:56:18 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
2019-01-30 12:06:32 +00:00
|
|
|
Factory* factory = isolate->factory();
|
2018-10-11 12:56:18 +00:00
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
|
|
|
|
|
|
|
Handle<Object> holdings1 = factory->NewStringFromAsciiChecked("holdings1");
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, holdings1, undefined, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> holdings2 = factory->NewStringFromAsciiChecked("holdings2");
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell2 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, holdings2, undefined, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> holdings3 = factory->NewStringFromAsciiChecked("holdings3");
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell3 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, holdings3, undefined, isolate);
|
2018-10-11 12:56:18 +00:00
|
|
|
|
|
|
|
NullifyWeakCell(weak_cell2, isolate);
|
|
|
|
NullifyWeakCell(weak_cell3, isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->NeedsCleanup());
|
|
|
|
Object cleared1 = JSFinalizationRegistry::PopClearedCellHoldings(
|
|
|
|
finalization_registry, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
CHECK_EQ(cleared1, *holdings3);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell3->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell3->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->NeedsCleanup());
|
|
|
|
Object cleared2 = JSFinalizationRegistry::PopClearedCellHoldings(
|
|
|
|
finalization_registry, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
CHECK_EQ(cleared2, *holdings2);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell2->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell2->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(!finalization_registry->NeedsCleanup());
|
2018-10-11 12:56:18 +00:00
|
|
|
|
|
|
|
NullifyWeakCell(weak_cell1, isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->NeedsCleanup());
|
|
|
|
Object cleared3 = JSFinalizationRegistry::PopClearedCellHoldings(
|
|
|
|
finalization_registry, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
CHECK_EQ(cleared3, *holdings1);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_cell1->prev().IsUndefined(isolate));
|
|
|
|
CHECK(weak_cell1->next().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(!finalization_registry->NeedsCleanup());
|
|
|
|
CHECK(finalization_registry->active_cells().IsUndefined(isolate));
|
|
|
|
CHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
|
2018-10-11 12:56:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
TEST(TestJSFinalizationRegistryPopClearedCellHoldings2) {
|
2019-01-30 12:06:32 +00:00
|
|
|
// Test that when all WeakCells for a key are popped, the key is removed from
|
|
|
|
// the key map.
|
2018-10-23 08:30:25 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
2019-01-30 12:06:32 +00:00
|
|
|
Factory* factory = isolate->factory();
|
2018-10-23 08:30:25 +00:00
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> holdings1 = factory->NewStringFromAsciiChecked("holdings1");
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, holdings1, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> holdings2 = factory->NewStringFromAsciiChecked("holdings2");
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell2 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, holdings2, token1, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
NullifyWeakCell(weak_cell1, isolate);
|
|
|
|
NullifyWeakCell(weak_cell2, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Nullifying doesn't affect the key chains (just moves WeakCells from
|
|
|
|
// active_cells to cleared_cells).
|
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell2,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1);
|
|
|
|
}
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Object cleared1 = JSFinalizationRegistry::PopClearedCellHoldings(
|
|
|
|
finalization_registry, isolate);
|
2019-01-31 08:54:38 +00:00
|
|
|
CHECK_EQ(cleared1, *holdings2);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Object cleared2 = JSFinalizationRegistry::PopClearedCellHoldings(
|
|
|
|
finalization_registry, isolate);
|
2019-01-31 08:54:38 +00:00
|
|
|
CHECK_EQ(cleared2, *holdings1);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TestUnregisterActiveCells) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
|
|
|
Handle<JSObject> token2 = CreateKey("token2", isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1a = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
|
|
|
Handle<WeakCell> weak_cell1b = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell2a = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
|
|
|
Handle<WeakCell> weak_cell2b = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 4,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2b, *weak_cell2a, *weak_cell1b, *weak_cell1a);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1a);
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2a);
|
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
|
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2a);
|
|
|
|
}
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Both weak_cell1a and weak_cell1b removed from active_cells.
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 2,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2b, *weak_cell2a);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2018-10-23 08:30:25 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
TEST(TestUnregisterActiveAndClearedCells) {
|
2018-10-23 08:30:25 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
|
|
|
Handle<JSObject> token2 = CreateKey("token2", isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1a = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
|
|
|
Handle<WeakCell> weak_cell1b = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell2a = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
|
|
|
Handle<WeakCell> weak_cell2b = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
NullifyWeakCell(weak_cell2a, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 3,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2b, *weak_cell1b, *weak_cell1a);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 1,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2a);
|
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1a);
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell2a);
|
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
JSFinalizationRegistry::Unregister(finalization_registry, token2, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
// Both weak_cell2a and weak_cell2b removed.
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 2,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1b, *weak_cell1a);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1a);
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
2018-10-23 08:30:25 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
TEST(TestWeakCellUnregisterTwice) {
|
2018-10-23 08:30:25 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 1,
|
2019-01-30 12:06:32 +00:00
|
|
|
*weak_cell1);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 1, *weak_cell1);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
|
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
|
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
2018-10-23 08:30:25 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 12:06:32 +00:00
|
|
|
TEST(TestWeakCellUnregisterPopped) {
|
2018-10-23 08:30:25 +00:00
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
2019-01-30 12:06:32 +00:00
|
|
|
Factory* factory = isolate->factory();
|
2018-10-23 08:30:25 +00:00
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<Object> holdings1 = factory->NewStringFromAsciiChecked("holdings1");
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1 = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, holdings1, token1, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
|
|
|
|
NullifyWeakCell(weak_cell1, isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
CHECK(finalization_registry->NeedsCleanup());
|
|
|
|
Object cleared1 = JSFinalizationRegistry::PopClearedCellHoldings(
|
|
|
|
finalization_registry, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
CHECK_EQ(cleared1, *holdings1);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
|
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 0);
|
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
{
|
2019-12-19 21:20:50 +00:00
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 0);
|
2019-01-30 12:06:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TestWeakCellUnregisterNonexistentKey) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
2019-01-30 12:06:32 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
JSFinalizationRegistry::Unregister(finalization_registry, token1, isolate);
|
2018-10-23 08:30:25 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 13:22:01 +00:00
|
|
|
TEST(TestJSWeakRef) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
|
|
|
Handle<JSWeakRef> weak_ref;
|
|
|
|
{
|
|
|
|
HandleScope inner_scope(isolate);
|
|
|
|
|
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
// This doesn't add the target into the KeepDuringJob set.
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<JSWeakRef> inner_weak_ref = ConstructJSWeakRef(js_object, isolate);
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
CcTest::CollectAllGarbage();
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!inner_weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
weak_ref = inner_scope.CloseAndEscape(inner_weak_ref);
|
|
|
|
}
|
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
CcTest::CollectAllGarbage();
|
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TestJSWeakRefIncrementalMarking) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
if (!FLAG_incremental_marking) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ManualGCScope manual_gc_scope;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
Heap* heap = isolate->heap();
|
|
|
|
HandleScope outer_scope(isolate);
|
|
|
|
Handle<JSWeakRef> weak_ref;
|
|
|
|
{
|
|
|
|
HandleScope inner_scope(isolate);
|
|
|
|
|
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
// This doesn't add the target into the KeepDuringJob set.
|
2019-01-30 12:06:32 +00:00
|
|
|
Handle<JSWeakRef> inner_weak_ref = ConstructJSWeakRef(js_object, isolate);
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
heap::SimulateIncrementalMarking(heap, true);
|
|
|
|
CcTest::CollectAllGarbage();
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!inner_weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
weak_ref = inner_scope.CloseAndEscape(inner_weak_ref);
|
|
|
|
}
|
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
heap::SimulateIncrementalMarking(heap, true);
|
|
|
|
CcTest::CollectAllGarbage();
|
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TestJSWeakRefKeepDuringJob) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-19 01:22:49 +00:00
|
|
|
Handle<JSWeakRef> weak_ref = MakeWeakRefAndKeepDuringJob(isolate);
|
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
|
|
|
CcTest::CollectAllGarbage();
|
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
2020-02-19 01:22:49 +00:00
|
|
|
// Clears the KeepDuringJob set.
|
|
|
|
context->GetIsolate()->ClearKeptObjects();
|
|
|
|
CcTest::CollectAllGarbage();
|
|
|
|
CHECK(weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
2020-02-19 01:22:49 +00:00
|
|
|
weak_ref = MakeWeakRefAndKeepDuringJob(isolate);
|
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
|
|
|
CcTest::CollectAllGarbage();
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
2020-02-19 01:22:49 +00:00
|
|
|
// ClearKeptObjects should be called by PerformMicrotasksCheckpoint.
|
|
|
|
CcTest::isolate()->PerformMicrotaskCheckpoint();
|
2018-12-17 13:22:01 +00:00
|
|
|
CcTest::CollectAllGarbage();
|
2020-02-19 01:22:49 +00:00
|
|
|
CHECK(weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
2020-02-19 01:22:49 +00:00
|
|
|
weak_ref = MakeWeakRefAndKeepDuringJob(isolate);
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
CcTest::CollectAllGarbage();
|
2020-02-19 01:22:49 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
2020-02-19 01:22:49 +00:00
|
|
|
// ClearKeptObjects should be called by MicrotasksScope::PerformCheckpoint.
|
|
|
|
v8::MicrotasksScope::PerformCheckpoint(CcTest::isolate());
|
|
|
|
CcTest::CollectAllGarbage();
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TestJSWeakRefKeepDuringJobIncrementalMarking) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
if (!FLAG_incremental_marking) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ManualGCScope manual_gc_scope;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
Heap* heap = isolate->heap();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-19 01:22:49 +00:00
|
|
|
Handle<JSWeakRef> weak_ref = MakeWeakRefAndKeepDuringJob(isolate);
|
2018-12-17 13:22:01 +00:00
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
heap::SimulateIncrementalMarking(heap, true);
|
|
|
|
CcTest::CollectAllGarbage();
|
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(!weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
|
|
|
|
// Clears the KeepDuringJob set.
|
2019-07-30 10:10:18 +00:00
|
|
|
context->GetIsolate()->ClearKeptObjects();
|
2018-12-17 13:22:01 +00:00
|
|
|
heap::SimulateIncrementalMarking(heap, true);
|
|
|
|
CcTest::CollectAllGarbage();
|
|
|
|
|
2019-05-23 07:47:44 +00:00
|
|
|
CHECK(weak_ref->target().IsUndefined(isolate));
|
2018-12-17 13:22:01 +00:00
|
|
|
}
|
|
|
|
|
2019-12-19 21:20:50 +00:00
|
|
|
TEST(TestRemoveUnregisterToken) {
|
|
|
|
FLAG_harmony_weak_refs = true;
|
|
|
|
CcTest::InitializeVM();
|
|
|
|
LocalContext context;
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
HandleScope outer_scope(isolate);
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<JSFinalizationRegistry> finalization_registry =
|
|
|
|
ConstructJSFinalizationRegistry(isolate);
|
2019-12-19 21:20:50 +00:00
|
|
|
Handle<JSObject> js_object =
|
|
|
|
isolate->factory()->NewJSObject(isolate->object_function());
|
|
|
|
|
|
|
|
Handle<JSObject> token1 = CreateKey("token1", isolate);
|
|
|
|
Handle<JSObject> token2 = CreateKey("token2", isolate);
|
|
|
|
Handle<Object> undefined =
|
|
|
|
handle(ReadOnlyRoots(isolate).undefined_value(), isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell1a = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
|
|
|
Handle<WeakCell> weak_cell1b = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token1, isolate);
|
2019-12-19 21:20:50 +00:00
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
Handle<WeakCell> weak_cell2a = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
|
|
|
Handle<WeakCell> weak_cell2b = FinalizationRegistryRegister(
|
|
|
|
finalization_registry, js_object, undefined, token2, isolate);
|
2019-12-19 21:20:50 +00:00
|
|
|
|
|
|
|
NullifyWeakCell(weak_cell2a, isolate);
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 3,
|
2019-12-19 21:20:50 +00:00
|
|
|
*weak_cell2b, *weak_cell1b, *weak_cell1a);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 1,
|
2019-12-19 21:20:50 +00:00
|
|
|
*weak_cell2a);
|
|
|
|
{
|
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
|
|
|
|
*weak_cell1a);
|
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 2, *weak_cell2b,
|
|
|
|
*weak_cell2a);
|
|
|
|
}
|
|
|
|
|
2020-02-24 19:47:48 +00:00
|
|
|
finalization_registry->RemoveUnregisterToken(
|
2019-12-19 21:20:50 +00:00
|
|
|
JSReceiver::cast(*token2), isolate,
|
|
|
|
[undefined](WeakCell matched_cell) {
|
|
|
|
matched_cell.set_unregister_token(*undefined);
|
|
|
|
},
|
|
|
|
[](HeapObject, ObjectSlot, Object) {});
|
|
|
|
|
|
|
|
// Both weak_cell2a and weak_cell2b remain on the weak cell chains.
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->active_cells(), 3,
|
2019-12-19 21:20:50 +00:00
|
|
|
*weak_cell2b, *weak_cell1b, *weak_cell1a);
|
2020-02-24 19:47:48 +00:00
|
|
|
VerifyWeakCellChain(isolate, finalization_registry->cleared_cells(), 1,
|
2019-12-19 21:20:50 +00:00
|
|
|
*weak_cell2a);
|
|
|
|
|
|
|
|
// But both weak_cell2a and weak_cell2b are removed from the key chain.
|
|
|
|
{
|
|
|
|
SimpleNumberDictionary key_map =
|
2020-02-24 19:47:48 +00:00
|
|
|
SimpleNumberDictionary::cast(finalization_registry->key_map());
|
2019-12-19 21:20:50 +00:00
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token1, 2, *weak_cell1b,
|
|
|
|
*weak_cell1a);
|
|
|
|
VerifyWeakCellKeyChain(isolate, key_map, *token2, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-11 12:56:18 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|