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

View File

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

View File

@ -27,7 +27,7 @@ fn default_to_string<'gc>(
pub enum Attribute {
DontDelete,
// DontEnum,
// ReadOnly,
ReadOnly,
}
#[derive(Clone)]
@ -69,11 +69,13 @@ impl<'gc> Property<'gc> {
function(avm, context, this, &[new_value]);
}
}
Property::Stored { value, .. } => {
Property::Stored { value, attributes, .. } => {
if !attributes.contains(Attribute::ReadOnly) {
replace::<Value<'gc>>(value, new_value);
}
}
}
}
pub fn can_delete(&self) -> bool {
match self {
@ -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]
fn test_virtual_get() {
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("stored"), true);
assert_eq!(object.write(context.gc_context).delete("stored_un"), false);
assert_eq!(object.write(context.gc_context).delete("non_existent"), false);
assert_eq!(
object.read().get("virtual", avm, context, object),