avm2: Extract `MethodFlags` enum
This commit is contained in:
parent
afd24cad12
commit
78ebf06f55
|
@ -22,8 +22,8 @@ use std::borrow::Cow;
|
|||
use std::cmp::{min, Ordering};
|
||||
use swf::avm2::read::Reader;
|
||||
use swf::avm2::types::{
|
||||
Class as AbcClass, Index, Method as AbcMethod, Multiname as AbcMultiname,
|
||||
Namespace as AbcNamespace, Op,
|
||||
Class as AbcClass, Index, Method as AbcMethod, MethodFlags as AbcMethodFlags,
|
||||
Multiname as AbcMultiname, Namespace as AbcNamespace, Op,
|
||||
};
|
||||
|
||||
/// Represents a particular register set.
|
||||
|
@ -407,7 +407,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
*write.get_mut(0).unwrap() = this.map(|t| t.into()).unwrap_or(Value::Null);
|
||||
}
|
||||
|
||||
let activation_class = if method.method().needs_activation {
|
||||
let activation_class = if method
|
||||
.method()
|
||||
.flags
|
||||
.contains(AbcMethodFlags::NEED_ACTIVATION)
|
||||
{
|
||||
let translation_unit = method.translation_unit();
|
||||
let abc_method = method.method();
|
||||
let mut dummy_activation = Activation::from_nothing(context.reborrow());
|
||||
|
@ -454,9 +458,13 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
}
|
||||
|
||||
if has_rest_or_args {
|
||||
let args_array = if method.method().needs_arguments_object {
|
||||
let args_array = if method
|
||||
.method()
|
||||
.flags
|
||||
.contains(AbcMethodFlags::NEED_ARGUMENTS)
|
||||
{
|
||||
ArrayStorage::from_args(&arguments_list)
|
||||
} else if method.method().needs_rest {
|
||||
} else if method.method().flags.contains(AbcMethodFlags::NEED_REST) {
|
||||
if let Some(rest_args) = arguments_list.get(signature.len()..) {
|
||||
ArrayStorage::from_args(rest_args)
|
||||
} else {
|
||||
|
@ -468,7 +476,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
|
||||
let mut args_object = ArrayObject::from_storage(&mut activation, args_array)?;
|
||||
|
||||
if method.method().needs_arguments_object {
|
||||
if method
|
||||
.method()
|
||||
.flags
|
||||
.contains(AbcMethodFlags::NEED_ARGUMENTS)
|
||||
{
|
||||
args_object.set_property(
|
||||
&QName::new(Namespace::public(), "callee").into(),
|
||||
callee.into(),
|
||||
|
|
|
@ -11,7 +11,8 @@ use gc_arena::{Collect, CollectionContext, Gc, MutationContext};
|
|||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use swf::avm2::types::{
|
||||
AbcFile, Index, Method as AbcMethod, MethodBody as AbcMethodBody, MethodParam as AbcMethodParam,
|
||||
AbcFile, Index, Method as AbcMethod, MethodBody as AbcMethodBody,
|
||||
MethodFlags as AbcMethodFlags, MethodParam as AbcMethodParam,
|
||||
};
|
||||
|
||||
/// Represents a function defined in Ruffle's code.
|
||||
|
@ -241,7 +242,9 @@ impl<'gc> BytecodeMethod<'gc> {
|
|||
///
|
||||
/// Variadic methods shove excess parameters into a final register.
|
||||
pub fn is_variadic(&self) -> bool {
|
||||
self.method().needs_arguments_object || self.method().needs_rest
|
||||
self.method()
|
||||
.flags
|
||||
.intersects(AbcMethodFlags::NEED_ARGUMENTS | AbcMethodFlags::NEED_REST)
|
||||
}
|
||||
|
||||
/// Determine if a given method is unchecked.
|
||||
|
@ -262,7 +265,7 @@ impl<'gc> BytecodeMethod<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
!self.method().needs_rest
|
||||
!self.method().flags.contains(AbcMethodFlags::NEED_REST)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,7 +374,7 @@ impl<'gc> Method<'gc> {
|
|||
pub fn needs_arguments_object(&self) -> bool {
|
||||
match self {
|
||||
Method::Native { .. } => false,
|
||||
Method::Bytecode(bm) => bm.method().needs_arguments_object,
|
||||
Method::Bytecode(bm) => bm.method().flags.contains(AbcMethodFlags::NEED_ARGUMENTS),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,9 +253,9 @@ impl<'a> Reader<'a> {
|
|||
})
|
||||
}
|
||||
let name = self.read_index()?;
|
||||
let flags = self.read_u8()?;
|
||||
let flags = MethodFlags::from_bits_truncate(self.read_u8()?);
|
||||
|
||||
if flags & 0x08 != 0 {
|
||||
if flags.contains(MethodFlags::HAS_OPTIONAL) {
|
||||
let num_optional_params = self.read_u30()? as usize;
|
||||
if let Some(start) = params.len().checked_sub(num_optional_params) {
|
||||
for param in &mut params[start..] {
|
||||
|
@ -266,7 +266,7 @@ impl<'a> Reader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
if flags & 0x80 != 0 {
|
||||
if flags.contains(MethodFlags::HAS_PARAM_NAMES) {
|
||||
for param in &mut params {
|
||||
param.name = Some(self.read_index()?);
|
||||
}
|
||||
|
@ -276,10 +276,7 @@ impl<'a> Reader<'a> {
|
|||
name,
|
||||
params,
|
||||
return_type,
|
||||
needs_arguments_object: flags & 0x01 != 0,
|
||||
needs_activation: flags & 0x02 != 0,
|
||||
needs_rest: flags & 0x04 != 0,
|
||||
needs_dxns: flags & 0x40 != 0,
|
||||
flags,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use bitflags::bitflags;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -98,10 +99,20 @@ pub struct Method {
|
|||
pub name: Index<String>,
|
||||
pub params: Vec<MethodParam>,
|
||||
pub return_type: Index<Multiname>,
|
||||
pub needs_arguments_object: bool,
|
||||
pub needs_activation: bool,
|
||||
pub needs_rest: bool,
|
||||
pub needs_dxns: bool,
|
||||
pub flags: MethodFlags,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct MethodFlags: u8 {
|
||||
const NEED_ARGUMENTS = 1 << 0;
|
||||
const NEED_ACTIVATION = 1 << 1;
|
||||
const NEED_REST = 1 << 2;
|
||||
const HAS_OPTIONAL = 1 << 3;
|
||||
const IGNORE_REST = 1 << 4;
|
||||
const NATIVE = 1 << 5;
|
||||
const SET_DXNS = 1 << 6;
|
||||
const HAS_PARAM_NAMES = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
|
@ -341,18 +341,7 @@ impl<W: Write> Writer<W> {
|
|||
}
|
||||
}
|
||||
self.write_index(&method.name)?;
|
||||
self.write_u8(
|
||||
if has_param_names { 0x80 } else { 0 }
|
||||
| if method.needs_dxns { 0x40 } else { 0 }
|
||||
| if num_optional_params > 0 { 0x08 } else { 0 }
|
||||
| if method.needs_rest { 0x04 } else { 0 }
|
||||
| if method.needs_activation { 0x02 } else { 0 }
|
||||
| if method.needs_arguments_object {
|
||||
0x01
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)?;
|
||||
self.write_u8(method.flags.bits())?;
|
||||
|
||||
if num_optional_params > 0 {
|
||||
self.write_u30(num_optional_params)?;
|
||||
|
|
|
@ -2803,19 +2803,13 @@ pub fn avm2_tests() -> Vec<Avm2TestData> {
|
|||
name: Index::new(0),
|
||||
params: vec![],
|
||||
return_type: Index::new(1),
|
||||
needs_arguments_object: false,
|
||||
needs_activation: false,
|
||||
needs_rest: false,
|
||||
needs_dxns: false,
|
||||
flags: MethodFlags::empty(),
|
||||
},
|
||||
Method {
|
||||
name: Index::new(0),
|
||||
params: vec![],
|
||||
return_type: Index::new(0),
|
||||
needs_arguments_object: false,
|
||||
needs_activation: false,
|
||||
needs_rest: false,
|
||||
needs_dxns: false,
|
||||
flags: MethodFlags::empty(),
|
||||
},
|
||||
],
|
||||
metadata: vec![],
|
||||
|
|
Loading…
Reference in New Issue