Skip to content

Commit

Permalink
feat: extends frozen of LocalInformation for Object.seal and `Objec…
Browse files Browse the repository at this point in the history
…t.preventExtensions`
  • Loading branch information
sor4chi committed Oct 30, 2024
1 parent 1f5bafa commit dd8be57
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 10 deletions.
15 changes: 11 additions & 4 deletions checker/src/context/information.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use source_map::SpanWithSource;
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;

use crate::{
events::{Event, RootReference},
Expand Down Expand Up @@ -32,8 +32,8 @@ pub struct LocalInformation {
/// `ContextId` is a mini context
pub(crate) closure_current_values: HashMap<(ClosureId, RootReference), TypeId>,

/// Not writeable, `TypeError: Cannot add property t, object is not extensible`. TODO conditional ?
pub(crate) frozen: HashSet<TypeId>,
/// Not writeable, `TypeError: Cannot add property, object is not extensible`. TODO conditional ?
pub(crate) frozen: HashMap<TypeId, ObjectProtectionState>,

/// Object type (LHS), must always be RHS
///
Expand All @@ -52,6 +52,13 @@ pub struct LocalInformation {
pub(crate) value_of_this: ThisValue,
}

#[derive(Debug, Clone, Copy, binary_serialize_derive::BinarySerializable)]
pub enum ObjectProtectionState {
Frozen,
Sealed,
NoExtensions,
}

#[derive(Debug, Default, binary_serialize_derive::BinarySerializable, Clone)]
pub(crate) enum ReturnState {
#[default]
Expand Down Expand Up @@ -228,7 +235,7 @@ impl LocalInformation {
.extend(other.current_properties.iter().map(|(l, r)| (*l, r.clone())));
self.closure_current_values
.extend(other.closure_current_values.iter().map(|(l, r)| (l.clone(), *r)));
self.frozen.extend(other.frozen.iter().clone());
self.frozen.extend(other.frozen.clone());
self.narrowed_values.extend(other.narrowed_values.iter().copied());
self.state = other.state.clone();
}
Expand Down
3 changes: 2 additions & 1 deletion checker/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod information;
pub mod invocation;
mod root;

use information::ObjectProtectionState;
pub(crate) use invocation::CallCheckingBehavior;
pub use root::RootContext;

Expand Down Expand Up @@ -518,7 +519,7 @@ impl<T: ContextType> Context<T> {
}

/// TODO doesn't look at aliases using `get_type_fact`!
pub fn is_frozen(&self, value: TypeId) -> Option<TypeId> {
pub fn is_frozen(&self, value: TypeId) -> Option<ObjectProtectionState> {
self.parents_iter().find_map(|ctx| get_on_ctx!(ctx.info.frozen.get(&value))).copied()
}

Expand Down
41 changes: 38 additions & 3 deletions checker/src/features/constant_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use iterator_endiate::EndiateIteratorExt;
use source_map::SpanWithSource;

use crate::{
context::{get_on_ctx, information::InformationChain, invocation::CheckThings},
context::{
get_on_ctx,
information::{InformationChain, ObjectProtectionState},
invocation::CheckThings,
},
events::printing::debug_effects,
features::objects::{ObjectBuilder, Proxy},
types::{
Expand Down Expand Up @@ -310,7 +314,27 @@ pub(crate) fn call_constant_function(
if let Some(on) =
(arguments.len() == 1).then(|| arguments[0].non_spread_type().ok()).flatten()
{
environment.info.frozen.insert(on);
environment.info.frozen.insert(on, ObjectProtectionState::Frozen);
Ok(ConstantOutput::Value(on))
} else {
Err(ConstantFunctionError::CannotComputeConstant)
}
}
"seal" => {
if let Some(on) =
(arguments.len() == 1).then(|| arguments[0].non_spread_type().ok()).flatten()
{
environment.info.frozen.insert(on, ObjectProtectionState::Sealed);
Ok(ConstantOutput::Value(on))
} else {
Err(ConstantFunctionError::CannotComputeConstant)
}
}
"preventExtensions" => {
if let Some(on) =
(arguments.len() == 1).then(|| arguments[0].non_spread_type().ok()).flatten()
{
environment.info.frozen.insert(on, ObjectProtectionState::NoExtensions);
Ok(ConstantOutput::Value(on))
} else {
Err(ConstantFunctionError::CannotComputeConstant)
Expand All @@ -321,12 +345,23 @@ pub(crate) fn call_constant_function(
(arguments.len() == 1).then(|| arguments[0].non_spread_type().ok()).flatten()
{
let is_frozen =
environment.get_chain_of_info().any(|info| info.frozen.contains(&on));
environment.get_chain_of_info().any(|info| info.frozen.contains_key(&on));
Ok(ConstantOutput::Value(if is_frozen { TypeId::TRUE } else { TypeId::FALSE }))
} else {
Err(ConstantFunctionError::CannotComputeConstant)
}
}
"isSealed" => {
if let Some(on) =
(arguments.len() == 1).then(|| arguments[0].non_spread_type().ok()).flatten()
{
let is_sealed =
environment.get_chain_of_info().any(|info| info.frozen.contains_key(&on));
Ok(ConstantOutput::Value(if is_sealed { TypeId::TRUE } else { TypeId::FALSE }))
} else {
Err(ConstantFunctionError::CannotComputeConstant)
}
}
"defineProperty" => {
// TODO check configurable
if let [on, property, descriptor] = arguments {
Expand Down
2 changes: 1 addition & 1 deletion checker/src/types/properties/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub fn set_property<B: CallCheckingBehavior>(
) -> SetPropertyResult {
// Frozen checks
{
if environment.info.frozen.contains(&on) {
if environment.info.frozen.contains_key(&on) {
return Err(SetPropertyError::NotWriteable {
property: PropertyKeyRepresentation::new(under, environment, types),
position,
Expand Down
4 changes: 3 additions & 1 deletion checker/src/types/subtyping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,9 @@ pub(crate) fn type_is_subtype_with_generics(
information,
types,
)
} else if information.get_chain_of_info().any(|info| info.frozen.contains(&ty))
} else if information
.get_chain_of_info()
.any(|info| info.frozen.contains_key(&ty))
|| matches!(subtype, Type::Constant(_))
|| matches!(
ty,
Expand Down

0 comments on commit dd8be57

Please sign in to comment.