avm1: Move current_swf_version and is_case_sensitive from avm1 to stackframe

This commit is contained in:
Nathan Adams 2020-06-28 15:42:42 +02:00
parent d470c52aea
commit f85684fec0
17 changed files with 70 additions and 86 deletions

View File

@ -354,18 +354,6 @@ impl<'gc> Avm1<'gc> {
!self.stack_frames.is_empty()
}
/// Get the currently executing SWF version.
pub fn current_swf_version(&self) -> u8 {
self.current_stack_frame()
.map(|sf| sf.read().swf_version())
.unwrap_or(self.player_version)
}
/// Returns whether property keys should be case sensitive based on the current SWF version.
pub fn is_case_sensitive(&self) -> bool {
is_swf_case_sensitive(self.current_swf_version())
}
pub fn notify_system_listeners(
&mut self,
active_clip: DisplayObject<'gc>,
@ -464,12 +452,6 @@ impl<'gc> Avm1<'gc> {
}
}
/// Returns whether the given SWF version is case-sensitive.
/// SWFv7 and above is case-sensitive.
pub fn is_swf_case_sensitive(swf_version: u8) -> bool {
swf_version > 6
}
pub fn root_error_handler<'gc>(
activation: &mut StackFrame<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,

View File

@ -272,7 +272,7 @@ impl<'gc> Executable<'gc> {
None
};
let effective_ver = if activation.avm().current_swf_version() > 5 {
let effective_ver = if activation.current_swf_version() > 5 {
af.swf_version()
} else {
this.as_display_object()

View File

@ -108,7 +108,7 @@ pub fn get_infinity<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() > 4 {
if activation.current_swf_version() > 4 {
Ok(f64::INFINITY.into())
} else {
Ok(Value::Undefined.into())
@ -121,7 +121,7 @@ pub fn get_nan<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() > 4 {
if activation.current_swf_version() > 4 {
Ok(f64::NAN.into())
} else {
Ok(Value::Undefined.into())

View File

@ -18,7 +18,7 @@ pub fn boolean<'gc>(
args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
let (ret_value, cons_value) = if let Some(val) = args.get(0) {
let b = Value::Bool(val.as_bool(activation.avm().current_swf_version()));
let b = Value::Bool(val.as_bool(activation.current_swf_version()));
(b.clone(), b)
} else {
(Value::Undefined, Value::Bool(false))

View File

@ -102,7 +102,7 @@ pub fn get_depth<'gc>(
_context: &mut UpdateContext<'_, 'gc, '_>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
let depth = display_object.depth().wrapping_sub(AVM_DEPTH_BIAS);
Ok(depth.into())
} else {

View File

@ -61,7 +61,7 @@ pub fn hit_test<'gc>(
let y = args.get(1).unwrap().coerce_to_f64(activation, context)?;
let shape = args
.get(2)
.map(|v| v.as_bool(activation.avm().current_swf_version()))
.map(|v| v.as_bool(activation.current_swf_version()))
.unwrap_or(false);
if shape {
log::warn!("Ignoring shape hittest and using bounding box instead. Shape based hit detection is not yet implemented. See https://github.com/ruffle-rs/ruffle/issues/177");
@ -174,7 +174,7 @@ fn line_style<'gc>(
};
let is_pixel_hinted = args
.get(3)
.map_or(false, |v| v.as_bool(activation.avm().current_swf_version()));
.map_or(false, |v| v.as_bool(activation.current_swf_version()));
let (allow_scale_x, allow_scale_y) = match args
.get(4)
.and_then(|v| v.coerce_to_string(activation, context).ok())
@ -574,7 +574,7 @@ fn create_text_field<'gc>(
);
text_field.post_instantiation(activation.avm(), context, text_field, None, true);
if activation.avm().current_swf_version() >= 8 {
if activation.current_swf_version() >= 8 {
//SWF8+ returns the `TextField` instance here
Ok(text_field.object().into())
} else {
@ -682,7 +682,7 @@ fn get_next_highest_depth<'gc>(
_context: &mut UpdateContext<'_, 'gc, '_>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 7 {
if activation.current_swf_version() >= 7 {
let depth = std::cmp::max(
movie_clip
.highest_depth()

View File

@ -207,7 +207,7 @@ fn duration<'gc>(
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
if let Some(sound_object) = this.as_sound_object() {
return Ok(sound_object.duration().into());
} else {
@ -224,7 +224,7 @@ fn get_bytes_loaded<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
log::warn!("Sound.getBytesLoaded: Unimplemented");
Ok(1.into())
} else {
@ -238,7 +238,7 @@ fn get_bytes_total<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
log::warn!("Sound.getBytesTotal: Unimplemented");
Ok(1.into())
} else {
@ -282,7 +282,7 @@ fn id3<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
log::warn!("Sound.id3: Unimplemented");
}
Ok(Value::Undefined.into())
@ -294,7 +294,7 @@ fn load_sound<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
log::warn!("Sound.loadSound: Unimplemented");
}
Ok(Value::Undefined.into())
@ -306,7 +306,7 @@ fn position<'gc>(
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if activation.avm().current_swf_version() >= 6 {
if activation.current_swf_version() >= 6 {
if let Some(sound_object) = this.as_sound_object() {
// TODO: The position is "sticky"; even if the sound is no longer playing, it should return
// the previous valid position.

View File

@ -450,7 +450,7 @@ pub fn set_use_code_page<'gc>(
.get(0)
.unwrap_or(&Value::Undefined)
.to_owned()
.as_bool(activation.avm().current_swf_version());
.as_bool(activation.current_swf_version());
action_context.system.use_codepage = value;
@ -476,7 +476,7 @@ pub fn set_exact_settings<'gc>(
.get(0)
.unwrap_or(&Value::Undefined)
.to_owned()
.as_bool(activation.avm().current_swf_version());
.as_bool(activation.current_swf_version());
action_context.system.exact_settings = value;

View File

@ -78,10 +78,7 @@ pub fn set_html<'gc>(
if let Some(display_object) = this.as_display_object() {
if let Some(text_field) = display_object.as_edit_text() {
if let Some(value) = args.get(0) {
text_field.set_is_html(
context,
value.as_bool(activation.avm().current_swf_version()),
);
text_field.set_is_html(context, value.as_bool(activation.current_swf_version()));
}
}
}
@ -147,7 +144,7 @@ pub fn set_border<'gc>(
if let Some(display_object) = this.as_display_object() {
if let Some(text_field) = display_object.as_edit_text() {
if let Some(value) = args.get(0) {
let has_border = value.as_bool(activation.avm().current_swf_version());
let has_border = value.as_bool(activation.current_swf_version());
text_field.set_has_border(context.gc_context, has_border);
}
}
@ -179,7 +176,7 @@ pub fn set_embed_fonts<'gc>(
if let Some(display_object) = this.as_display_object() {
if let Some(text_field) = display_object.as_edit_text() {
if let Some(value) = args.get(0) {
let embed_fonts = value.as_bool(activation.avm().current_swf_version());
let embed_fonts = value.as_bool(activation.current_swf_version());
text_field.set_is_device_font(context, !embed_fonts);
}
}
@ -284,7 +281,7 @@ pub fn set_multiline<'gc>(
.get(0)
.cloned()
.unwrap_or(Value::Undefined)
.as_bool(activation.avm().current_swf_version());
.as_bool(activation.current_swf_version());
if let Some(etext) = this
.as_display_object()
@ -362,7 +359,7 @@ pub fn set_word_wrap<'gc>(
.get(0)
.cloned()
.unwrap_or(Value::Undefined)
.as_bool(activation.avm().current_swf_version());
.as_bool(activation.current_swf_version());
if let Some(etext) = this
.as_display_object()

View File

@ -55,7 +55,7 @@ fn map_defined_to_bool<'gc>(
Some(Value::Undefined) => Value::Null,
Some(Value::Null) => Value::Null,
None => Value::Null,
Some(v) => v.as_bool(activation.avm().current_swf_version()).into(),
Some(v) => v.as_bool(activation.current_swf_version()).into(),
};
this.set(name, val, activation, ac)?;

View File

@ -132,7 +132,7 @@ pub fn xmlnode_clone_node<'gc>(
if let (Some(xmlnode), deep) = (
this.as_xml_node(),
args.get(0)
.map(|v| v.as_bool(activation.avm().current_swf_version()))
.map(|v| v.as_bool(activation.current_swf_version()))
.unwrap_or(false),
) {
let mut clone_node = xmlnode.duplicate(ac.gc_context, deep);

View File

@ -343,7 +343,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
proto_stack.push(p);
}
if activation.avm().current_swf_version() >= 7 {
if activation.current_swf_version() >= 7 {
for interface in this_proto.interfaces() {
if Object::ptr_eq(interface, constructor) {
return Ok(true);

View File

@ -228,7 +228,7 @@ impl<'gc> ScriptObject<'gc> {
.0
.read()
.values
.contains_key(name, activation.avm().is_case_sensitive());
.contains_key(name, activation.is_case_sensitive());
let mut rval = None;
if is_vacant {
@ -262,7 +262,7 @@ impl<'gc> ScriptObject<'gc> {
.0
.write(context.gc_context)
.values
.entry(name.to_owned(), activation.avm().is_case_sensitive())
.entry(name.to_owned(), activation.is_case_sensitive())
{
Entry::Occupied(mut entry) => Some(
entry
@ -313,7 +313,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
.0
.read()
.values
.get(name, activation.avm().is_case_sensitive())
.get(name, activation.is_case_sensitive())
{
return value
.get(activation, context, this, Some((*self).into()))?
@ -373,7 +373,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
.0
.write(context.gc_context)
.values
.get_mut(name, activation.avm().is_case_sensitive())
.get_mut(name, activation.is_case_sensitive())
{
Some(propref) if propref.is_virtual() => {
propref.set(activation, context, this, Some((*self).into()), value)
@ -410,14 +410,9 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
name: &str,
) -> bool {
let mut object = self.0.write(gc_context);
if let Some(prop) = object
.values
.get(name, activation.avm().is_case_sensitive())
{
if let Some(prop) = object.values.get(name, activation.is_case_sensitive()) {
if prop.can_delete() {
object
.values
.remove(name, activation.avm().is_case_sensitive());
object.values.remove(name, activation.is_case_sensitive());
return true;
}
}
@ -460,7 +455,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
set,
attributes,
},
activation.avm().is_case_sensitive(),
activation.is_case_sensitive(),
);
}
@ -538,7 +533,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
self.0
.read()
.values
.contains_key(name, activation.avm().is_case_sensitive())
.contains_key(name, activation.is_case_sensitive())
}
fn has_own_virtual(
@ -551,7 +546,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
.0
.read()
.values
.get(name, activation.avm().is_case_sensitive())
.get(name, activation.is_case_sensitive())
{
slot.is_virtual()
} else {
@ -563,7 +558,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
self.0
.read()
.values
.get(name, activation.avm().is_case_sensitive())
.get(name, activation.is_case_sensitive())
.map(|p| p.is_overwritable())
.unwrap_or(false)
}
@ -574,7 +569,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
.0
.read()
.values
.get(name, activation.avm().is_case_sensitive())
.get(name, activation.is_case_sensitive())
{
prop.is_enumerable()
} else {
@ -594,7 +589,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
out_keys.extend(proto_keys.into_iter().filter(|k| {
!object
.values
.contains_key(k, activation.avm().is_case_sensitive())
.contains_key(k, activation.is_case_sensitive())
}));
// Then our own keys.

View File

@ -291,10 +291,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
// AS1 logical and
let a = self.avm.pop();
let b = self.avm.pop();
let version = self.avm.current_swf_version();
let version = self.current_swf_version();
let result = b.as_bool(version) && a.as_bool(version);
self.avm
.push(Value::from_bool(result, self.avm.current_swf_version()));
.push(Value::from_bool(result, self.current_swf_version()));
Ok(FrameControl::Continue)
}
@ -436,7 +436,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
for action in clip.actions_on_frame(context, frame) {
self.avm.run_stack_frame_for_action(
self.target_clip_or_root(),
self.avm.current_swf_version(),
self.current_swf_version(),
action,
context,
);
@ -800,7 +800,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
let b = self.avm.pop();
let result = b.into_number_v1() == a.into_number_v1();
self.avm
.push(Value::from_bool(result, self.avm.current_swf_version()));
.push(Value::from_bool(result, self.current_swf_version()));
Ok(FrameControl::Continue)
}
@ -1121,7 +1121,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
reader: &mut Reader<'_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
let val = self.avm.pop();
if val.as_bool(self.avm.current_swf_version()) {
if val.as_bool(self.current_swf_version()) {
reader.seek(jump_offset.into());
}
Ok(FrameControl::Continue)
@ -1228,7 +1228,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
let b = self.avm.pop();
let result = b.into_number_v1() < a.into_number_v1();
self.avm
.push(Value::from_bool(result, self.avm.current_swf_version()));
.push(Value::from_bool(result, self.current_swf_version()));
Ok(FrameControl::Continue)
}
@ -1336,7 +1336,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
&mut self,
_context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<FrameControl<'gc>, Error<'gc>> {
let version = self.avm.current_swf_version();
let version = self.current_swf_version();
let val = !self.avm.pop().as_bool(version);
self.avm.push(Value::from_bool(val, version));
Ok(FrameControl::Continue)
@ -1386,7 +1386,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
Attribute::DontEnum.into(),
EnumSet::empty(),
);
if self.avm.current_swf_version() < 7 {
if self.current_swf_version() < 7 {
this.set("constructor", constructor.into(), self, context)?;
this.set_attributes(
context.gc_context,
@ -1441,7 +1441,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
Attribute::DontEnum.into(),
EnumSet::empty(),
);
if self.avm.current_swf_version() < 7 {
if self.current_swf_version() < 7 {
this.set("constructor", constructor.into(), self, context)?;
this.set_attributes(
context.gc_context,
@ -1465,7 +1465,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
// AS1 logical or
let a = self.avm.pop();
let b = self.avm.pop();
let version = self.avm.current_swf_version();
let version = self.current_swf_version();
let result = b.as_bool(version) || a.as_bool(version);
self.avm.push(Value::from_bool(result, version));
Ok(FrameControl::Continue)
@ -1767,7 +1767,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
let display_object = self.resolve_target_display_object(context, start_clip, target)?;
if let Some(display_object) = display_object {
let lock_center = self.avm.pop();
let constrain = self.avm.pop().as_bool(self.avm.current_swf_version());
let constrain = self.avm.pop().as_bool(self.current_swf_version());
if constrain {
let y2 = self.avm.pop();
let x2 = self.avm.pop();
@ -1847,7 +1847,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
let b = self.avm.pop();
let result = b.coerce_to_string(self, context)? == a.coerce_to_string(self, context)?;
self.avm
.push(Value::from_bool(result, self.avm.current_swf_version()));
.push(Value::from_bool(result, self.current_swf_version()));
Ok(FrameControl::Continue)
}
@ -1886,7 +1886,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
.bytes()
.gt(a.coerce_to_string(self, context)?.bytes());
self.avm
.push(Value::from_bool(result, self.avm.current_swf_version()));
.push(Value::from_bool(result, self.current_swf_version()));
Ok(FrameControl::Continue)
}
@ -1916,7 +1916,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
.bytes()
.lt(a.coerce_to_string(self, context)?.bytes());
self.avm
.push(Value::from_bool(result, self.avm.current_swf_version()));
.push(Value::from_bool(result, self.current_swf_version()));
Ok(FrameControl::Continue)
}
@ -2248,7 +2248,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
(start, false)
};
let case_sensitive = self.avm().is_case_sensitive();
let case_sensitive = self.is_case_sensitive();
// Iterate through each token in the path.
while !path.is_empty() {
@ -2594,4 +2594,14 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
pub fn root_object(&self, _context: &mut UpdateContext<'_, 'gc, '_>) -> Value<'gc> {
self.base_clip().root().object()
}
/// Get the currently executing SWF version.
pub fn current_swf_version(&self) -> u8 {
self.activation.read().swf_version()
}
/// Returns whether property keys should be case sensitive based on the current SWF version.
pub fn is_case_sensitive(&self) -> bool {
self.current_swf_version() > 6
}
}

View File

@ -133,7 +133,7 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
) -> Result<Value<'gc>, Error<'gc>> {
let obj = self.0.read();
let props = activation.avm().display_properties;
let case_sensitive = activation.avm().is_case_sensitive();
let case_sensitive = activation.is_case_sensitive();
// Property search order for DisplayObjects:
if self.has_own_property(activation, context, name) {
// 1) Actual properties on the underlying object
@ -347,7 +347,7 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
return true;
}
let case_sensitive = activation.avm().is_case_sensitive();
let case_sensitive = activation.is_case_sensitive();
if obj
.display_object
.get_child_by_name(name, case_sensitive)

View File

@ -162,15 +162,15 @@ impl<'gc> Value<'gc> {
_context: &mut UpdateContext<'_, 'gc, '_>,
) -> f64 {
match self {
Value::Undefined if activation.avm().current_swf_version() < 7 => 0.0,
Value::Null if activation.avm().current_swf_version() < 7 => 0.0,
Value::Undefined if activation.current_swf_version() < 7 => 0.0,
Value::Null if activation.current_swf_version() < 7 => 0.0,
Value::Undefined => NAN,
Value::Null => NAN,
Value::Bool(false) => 0.0,
Value::Bool(true) => 1.0,
Value::Number(v) => *v,
Value::String(v) => match v.as_str() {
v if activation.avm().current_swf_version() >= 6 && v.starts_with("0x") => {
v if activation.current_swf_version() >= 6 && v.starts_with("0x") => {
let mut n: u32 = 0;
for c in v[2..].bytes() {
n = n.wrapping_shl(4);
@ -196,7 +196,7 @@ impl<'gc> Value<'gc> {
}
f64::from(n as i32)
}
v if activation.avm().current_swf_version() >= 6
v if activation.current_swf_version() >= 6
&& (v.starts_with('0') || v.starts_with("+0") || v.starts_with("-0"))
&& v[1..].bytes().all(|c| c >= b'0' && c <= b'7') =>
{
@ -470,7 +470,7 @@ impl<'gc> Value<'gc> {
}
}
Value::Undefined => {
if activation.avm().current_swf_version() >= 7 {
if activation.current_swf_version() >= 7 {
Cow::Borrowed("undefined")
} else {
Cow::Borrowed("")

View File

@ -118,7 +118,7 @@ fn getbool_from_avm1_object<'gc>(
Ok(match object.get(name, activation, uc)? {
Value::Undefined => None,
Value::Null => None,
v => Some(v.as_bool(activation.avm().current_swf_version())),
v => Some(v.as_bool(activation.current_swf_version())),
})
}