forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LibJS: Implement WeakRef changes from 'Symbol as WeakMap Keys Proposal'
- Loading branch information
Showing
6 changed files
with
69 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (c) 2021, Idan Horowitz <[email protected]> | ||
* Copyright (c) 2021-2022, Idan Horowitz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
@@ -8,26 +8,38 @@ | |
|
||
namespace JS { | ||
|
||
WeakRef* WeakRef::create(GlobalObject& global_object, Object* object) | ||
WeakRef* WeakRef::create(GlobalObject& global_object, Object& value) | ||
{ | ||
return global_object.heap().allocate<WeakRef>(global_object, object, *global_object.weak_ref_prototype()); | ||
return global_object.heap().allocate<WeakRef>(global_object, value, *global_object.weak_ref_prototype()); | ||
} | ||
|
||
WeakRef::WeakRef(Object* object, Object& prototype) | ||
WeakRef* WeakRef::create(GlobalObject& global_object, Symbol& value) | ||
{ | ||
return global_object.heap().allocate<WeakRef>(global_object, value, *global_object.weak_ref_prototype()); | ||
} | ||
|
||
WeakRef::WeakRef(Object& value, Object& prototype) | ||
: Object(prototype) | ||
, WeakContainer(heap()) | ||
, m_value(&value) | ||
, m_last_execution_generation(vm().execution_generation()) | ||
{ | ||
} | ||
|
||
WeakRef::WeakRef(Symbol& value, Object& prototype) | ||
: Object(prototype) | ||
, WeakContainer(heap()) | ||
, m_value(object) | ||
, m_value(&value) | ||
, m_last_execution_generation(vm().execution_generation()) | ||
{ | ||
} | ||
|
||
void WeakRef::remove_dead_cells(Badge<Heap>) | ||
{ | ||
VERIFY(m_value); | ||
if (m_value->state() == Cell::State::Live) | ||
if (m_value.visit([](Cell* cell) -> bool { return cell->state() == Cell::State::Live; }, [](Empty) -> bool { VERIFY_NOT_REACHED(); })) | ||
return; | ||
|
||
m_value = nullptr; | ||
m_value = Empty {}; | ||
// This is an optimization, we deregister from the garbage collector early (even if we were not garbage collected ourself yet) | ||
// to reduce the garbage collection overhead, which we can do because a cleared weak ref cannot be reused. | ||
WeakContainer::deregister(); | ||
|
@@ -37,8 +49,10 @@ void WeakRef::visit_edges(Visitor& visitor) | |
{ | ||
Base::visit_edges(visitor); | ||
|
||
if (vm().execution_generation() == m_last_execution_generation) | ||
visitor.visit(m_value); | ||
if (vm().execution_generation() == m_last_execution_generation) { | ||
auto* cell = m_value.visit([](Cell* cell) -> Cell* { return cell; }, [](Empty) -> Cell* { return nullptr; }); | ||
visitor.visit(cell); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (c) 2021, Idan Horowitz <[email protected]> | ||
* Copyright (c) 2021-2022, Idan Horowitz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
@@ -18,12 +18,14 @@ class WeakRef final | |
JS_OBJECT(WeakRef, Object); | ||
|
||
public: | ||
static WeakRef* create(GlobalObject&, Object*); | ||
static WeakRef* create(GlobalObject&, Object&); | ||
static WeakRef* create(GlobalObject&, Symbol&); | ||
|
||
explicit WeakRef(Object*, Object& prototype); | ||
explicit WeakRef(Object&, Object& prototype); | ||
explicit WeakRef(Symbol&, Object& prototype); | ||
virtual ~WeakRef() override = default; | ||
|
||
Object* value() const { return m_value; }; | ||
auto const& value() const { return m_value; }; | ||
|
||
void update_execution_generation() { m_last_execution_generation = vm().execution_generation(); }; | ||
|
||
|
@@ -32,7 +34,7 @@ class WeakRef final | |
private: | ||
virtual void visit_edges(Visitor&) override; | ||
|
||
Object* m_value { nullptr }; | ||
Variant<Object*, Symbol*, Empty> m_value; | ||
u32 m_last_execution_generation { 0 }; | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (c) 2021, Idan Horowitz <[email protected]> | ||
* Copyright (c) 2021-2022, Idan Horowitz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
@@ -42,9 +42,13 @@ ThrowCompletionOr<Object*> WeakRefConstructor::construct(FunctionObject& new_tar | |
auto& global_object = this->global_object(); | ||
|
||
auto target = vm.argument(0); | ||
if (!target.is_object()) | ||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects()); | ||
return TRY(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object())); | ||
if (!can_be_held_weakly(target)) | ||
return vm.throw_completion<TypeError>(global_object, ErrorType::CannotBeHeldWeakly, target.to_string_without_side_effects()); | ||
|
||
if (target.is_object()) | ||
return TRY(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, target.as_object())); | ||
VERIFY(target.is_symbol()); | ||
return TRY(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, target.as_symbol())); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (c) 2021, Idan Horowitz <[email protected]> | ||
* Copyright (c) 2021-2022, Idan Horowitz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
@@ -30,7 +30,9 @@ JS_DEFINE_NATIVE_FUNCTION(WeakRefPrototype::deref) | |
auto* weak_ref = TRY(typed_this_object(global_object)); | ||
|
||
weak_ref->update_execution_generation(); | ||
return weak_ref->value() ?: js_undefined(); | ||
return weak_ref->value().visit( | ||
[](Empty) -> Value { return js_undefined(); }, | ||
[](auto* value) -> Value { return value; }); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters