Add Attribute::ReadOnly

This commit is contained in:
Nathan Adams 2019-10-08 15:24:57 +02:00
parent f2a4000ee2
commit f782aaee18
3 changed files with 72 additions and 16 deletions

View File

@ -17,7 +17,7 @@ macro_rules! wrap_std {
} }
}, },
$gc_context, $gc_context,
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
)* )*
}}; }};
@ -54,42 +54,42 @@ pub fn create<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Object<'
math.force_set( math.force_set(
"E", "E",
Value::Number(std::f64::consts::E), Value::Number(std::f64::consts::E),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"LN10", "LN10",
Value::Number(std::f64::consts::LN_10), Value::Number(std::f64::consts::LN_10),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"LN2", "LN2",
Value::Number(std::f64::consts::LN_2), Value::Number(std::f64::consts::LN_2),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"LOG10E", "LOG10E",
Value::Number(std::f64::consts::LOG10_E), Value::Number(std::f64::consts::LOG10_E),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"LOG2E", "LOG2E",
Value::Number(std::f64::consts::LOG2_E), Value::Number(std::f64::consts::LOG2_E),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"PI", "PI",
Value::Number(std::f64::consts::PI), Value::Number(std::f64::consts::PI),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"SQRT1_2", "SQRT1_2",
Value::Number(std::f64::consts::FRAC_1_SQRT_2), Value::Number(std::f64::consts::FRAC_1_SQRT_2),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
math.force_set( math.force_set(
"SQRT2", "SQRT2",
Value::Number(std::f64::consts::SQRT_2), Value::Number(std::f64::consts::SQRT_2),
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
wrap_std!(math, gc_context, wrap_std!(math, gc_context,
@ -107,8 +107,8 @@ pub fn create<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Object<'
"tan" => f64::tan "tan" => f64::tan
); );
math.force_set_function("atan2", atan2, gc_context, Attribute::DontDelete); math.force_set_function("atan2", atan2, gc_context, Attribute::DontDelete | Attribute::ReadOnly);
math.force_set_function("random", random, gc_context, Attribute::DontDelete); math.force_set_function("random", random, gc_context, Attribute::DontDelete | Attribute::ReadOnly);
GcCell::allocate(gc_context, math) GcCell::allocate(gc_context, math)
} }

View File

@ -17,7 +17,7 @@ macro_rules! with_movie_clip {
Value::Undefined Value::Undefined
}, },
$gc_context, $gc_context,
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
)* )*
}}; }};
@ -37,7 +37,7 @@ macro_rules! with_movie_clip_mut {
Value::Undefined Value::Undefined
}, },
$gc_context, $gc_context,
Attribute::DontDelete, Attribute::DontDelete | Attribute::ReadOnly,
); );
)* )*
}}; }};

View File

@ -27,7 +27,7 @@ fn default_to_string<'gc>(
pub enum Attribute { pub enum Attribute {
DontDelete, DontDelete,
// DontEnum, // DontEnum,
// ReadOnly, ReadOnly,
} }
#[derive(Clone)] #[derive(Clone)]
@ -69,8 +69,10 @@ impl<'gc> Property<'gc> {
function(avm, context, this, &[new_value]); function(avm, context, this, &[new_value]);
} }
} }
Property::Stored { value, .. } => { Property::Stored { value, attributes, .. } => {
replace::<Value<'gc>>(value, new_value); if !attributes.contains(Attribute::ReadOnly) {
replace::<Value<'gc>>(value, new_value);
}
} }
} }
} }
@ -456,6 +458,59 @@ mod tests {
}) })
} }
#[test]
fn test_set_readonly() {
with_object(0, |avm, context, object| {
object.write(context.gc_context).force_set(
"normal",
Value::String("initial".to_string()),
EnumSet::empty(),
);
object.write(context.gc_context).force_set(
"readonly",
Value::String("initial".to_string()),
Attribute::ReadOnly,
);
object.write(context.gc_context).set("normal", Value::String("replaced".to_string()), avm, context, object);
object.write(context.gc_context).set("readonly", Value::String("replaced".to_string()), avm, context, object);
assert_eq!(
object.read().get("normal", avm, context, object),
Value::String("replaced".to_string())
);
assert_eq!(
object.read().get("readonly", avm, context, object),
Value::String("initial".to_string())
);
})
}
#[test]
fn test_deletable_not_readonly() {
with_object(0, |avm, context, object| {
object.write(context.gc_context).force_set(
"test",
Value::String("initial".to_string()),
Attribute::DontDelete,
);
assert_eq!(object.write(context.gc_context).delete("test"), false);
assert_eq!(
object.read().get("test", avm, context, object),
Value::String("initial".to_string())
);
object.write(context.gc_context).set("test", Value::String("replaced".to_string()), avm, context, object);
assert_eq!(object.write(context.gc_context).delete("test"), false);
assert_eq!(
object.read().get("test", avm, context, object),
Value::String("replaced".to_string())
);
})
}
#[test] #[test]
fn test_virtual_get() { fn test_virtual_get() {
with_object(0, |avm, context, object| { with_object(0, |avm, context, object| {
@ -521,6 +576,7 @@ mod tests {
assert_eq!(object.write(context.gc_context).delete("virtual_un"), false); assert_eq!(object.write(context.gc_context).delete("virtual_un"), false);
assert_eq!(object.write(context.gc_context).delete("stored"), true); assert_eq!(object.write(context.gc_context).delete("stored"), true);
assert_eq!(object.write(context.gc_context).delete("stored_un"), false); assert_eq!(object.write(context.gc_context).delete("stored_un"), false);
assert_eq!(object.write(context.gc_context).delete("non_existent"), false);
assert_eq!( assert_eq!(
object.read().get("virtual", avm, context, object), object.read().get("virtual", avm, context, object),