swf: Use bitflags for Function flags
This commit is contained in:
parent
2b98c878f0
commit
f173b81e38
|
@ -12,7 +12,10 @@ use crate::tag_utils::SwfSlice;
|
|||
use gc_arena::{Collect, CollectionContext, Gc, GcCell, MutationContext};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use swf::{avm1::types::FunctionParam, SwfStr};
|
||||
use swf::{
|
||||
avm1::types::{FunctionFlags, FunctionParam},
|
||||
SwfStr,
|
||||
};
|
||||
|
||||
/// Represents a function defined in Ruffle's code.
|
||||
///
|
||||
|
@ -61,16 +64,6 @@ pub struct Avm1Function<'gc> {
|
|||
/// set. Any register beyond this ID will be served from the global one.
|
||||
register_count: u8,
|
||||
|
||||
preload_parent: bool,
|
||||
preload_root: bool,
|
||||
suppress_super: bool,
|
||||
preload_super: bool,
|
||||
suppress_arguments: bool,
|
||||
preload_arguments: bool,
|
||||
suppress_this: bool,
|
||||
preload_this: bool,
|
||||
preload_global: bool,
|
||||
|
||||
/// The names of the function parameters and their register mappings.
|
||||
/// r0 indicates that no register shall be written and the parameter stored
|
||||
/// as a Variable instead.
|
||||
|
@ -85,6 +78,10 @@ pub struct Avm1Function<'gc> {
|
|||
/// The base movie clip that the function was defined on.
|
||||
/// This is the movie clip that contains the bytecode.
|
||||
base_clip: DisplayObject<'gc>,
|
||||
|
||||
/// The flags that define the preloaded registers of the function.
|
||||
#[collect(require_static)]
|
||||
flags: FunctionFlags,
|
||||
}
|
||||
|
||||
impl<'gc> Avm1Function<'gc> {
|
||||
|
@ -112,15 +109,6 @@ impl<'gc> Avm1Function<'gc> {
|
|||
data: actions,
|
||||
name,
|
||||
register_count: 0,
|
||||
preload_parent: false,
|
||||
preload_root: false,
|
||||
suppress_super: false,
|
||||
preload_super: false,
|
||||
suppress_arguments: false,
|
||||
preload_arguments: false,
|
||||
suppress_this: false,
|
||||
preload_this: false,
|
||||
preload_global: false,
|
||||
params: params
|
||||
.iter()
|
||||
.map(|&s| {
|
||||
|
@ -133,6 +121,7 @@ impl<'gc> Avm1Function<'gc> {
|
|||
scope,
|
||||
constant_pool,
|
||||
base_clip,
|
||||
flags: FunctionFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,19 +161,11 @@ impl<'gc> Avm1Function<'gc> {
|
|||
data: actions,
|
||||
name,
|
||||
register_count: swf_function.register_count,
|
||||
preload_parent: swf_function.preload_parent,
|
||||
preload_root: swf_function.preload_root,
|
||||
suppress_super: swf_function.suppress_super,
|
||||
preload_super: swf_function.preload_super,
|
||||
suppress_arguments: swf_function.suppress_arguments,
|
||||
preload_arguments: swf_function.preload_arguments,
|
||||
suppress_this: swf_function.suppress_this,
|
||||
preload_this: swf_function.preload_this,
|
||||
preload_global: swf_function.preload_global,
|
||||
params: owned_params,
|
||||
scope,
|
||||
constant_pool,
|
||||
base_clip,
|
||||
flags: swf_function.flags,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +262,7 @@ impl<'gc> Executable<'gc> {
|
|||
Attribute::DONT_ENUM,
|
||||
);
|
||||
|
||||
if !af.suppress_arguments {
|
||||
if !af.flags.contains(FunctionFlags::SUPPRESS_ARGUMENTS) {
|
||||
for i in 0..args.len() {
|
||||
arguments.set_array_element(
|
||||
i,
|
||||
|
@ -292,7 +273,8 @@ impl<'gc> Executable<'gc> {
|
|||
}
|
||||
|
||||
let argcell = arguments.into();
|
||||
let super_object: Option<Object<'gc>> = if !af.suppress_super {
|
||||
let super_object: Option<Object<'gc>> =
|
||||
if !af.flags.contains(FunctionFlags::SUPPRESS_SUPER) {
|
||||
Some(
|
||||
SuperObject::from_this_and_base_proto(
|
||||
this,
|
||||
|
@ -356,14 +338,14 @@ impl<'gc> Executable<'gc> {
|
|||
|
||||
let mut preload_r = 1;
|
||||
|
||||
if af.preload_this {
|
||||
if af.flags.contains(FunctionFlags::PRELOAD_THIS) {
|
||||
//TODO: What happens if you specify both suppress and
|
||||
//preload for this?
|
||||
frame.set_local_register(preload_r, this);
|
||||
preload_r += 1;
|
||||
}
|
||||
|
||||
if af.preload_arguments {
|
||||
if af.flags.contains(FunctionFlags::PRELOAD_ARGUMENTS) {
|
||||
//TODO: What happens if you specify both suppress and
|
||||
//preload for arguments?
|
||||
frame.set_local_register(preload_r, argcell);
|
||||
|
@ -371,7 +353,7 @@ impl<'gc> Executable<'gc> {
|
|||
}
|
||||
|
||||
if let Some(super_object) = super_object {
|
||||
if af.preload_super {
|
||||
if af.flags.contains(FunctionFlags::PRELOAD_SUPER) {
|
||||
frame.set_local_register(preload_r, super_object);
|
||||
//TODO: What happens if you specify both suppress and
|
||||
//preload for super?
|
||||
|
@ -381,7 +363,7 @@ impl<'gc> Executable<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
if af.preload_root {
|
||||
if af.flags.contains(FunctionFlags::PRELOAD_ROOT) {
|
||||
frame.set_local_register(
|
||||
preload_r,
|
||||
af.base_clip.avm1_root(&frame.context)?.object(),
|
||||
|
@ -389,7 +371,7 @@ impl<'gc> Executable<'gc> {
|
|||
preload_r += 1;
|
||||
}
|
||||
|
||||
if af.preload_parent {
|
||||
if af.flags.contains(FunctionFlags::PRELOAD_PARENT) {
|
||||
// If _parent is undefined (because this is a root timeline), it actually does not get pushed,
|
||||
// and _global ends up incorrectly taking _parent's register.
|
||||
// See test for more info.
|
||||
|
@ -399,7 +381,7 @@ impl<'gc> Executable<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
if af.preload_global {
|
||||
if af.flags.contains(FunctionFlags::PRELOAD_GLOBAL) {
|
||||
let global = frame.context.avm1.global_object();
|
||||
frame.set_local_register(preload_r, global);
|
||||
}
|
||||
|
|
|
@ -302,8 +302,8 @@ impl<'a> Reader<'a> {
|
|||
fn read_define_function_2(&mut self, action_length: &mut usize) -> Result<Action<'a>> {
|
||||
let name = self.read_str()?;
|
||||
let num_params = self.read_u16()?;
|
||||
let register_count = self.read_u8()?; // Number of registers
|
||||
let flags = self.read_u16()?;
|
||||
let register_count = self.read_u8()?;
|
||||
let flags = FunctionFlags::from_bits_truncate(self.read_u16()?);
|
||||
let mut params = Vec::with_capacity(num_params as usize);
|
||||
for _ in 0..num_params {
|
||||
let register = self.read_u8()?;
|
||||
|
@ -319,15 +319,7 @@ impl<'a> Reader<'a> {
|
|||
name,
|
||||
params,
|
||||
register_count,
|
||||
preload_global: flags & 0b1_00000000 != 0,
|
||||
preload_parent: flags & 0b10000000 != 0,
|
||||
preload_root: flags & 0b1000000 != 0,
|
||||
suppress_super: flags & 0b100000 != 0,
|
||||
preload_super: flags & 0b10000 != 0,
|
||||
suppress_arguments: flags & 0b1000 != 0,
|
||||
preload_arguments: flags & 0b100 != 0,
|
||||
suppress_this: flags & 0b10 != 0,
|
||||
preload_this: flags & 0b1 != 0,
|
||||
flags,
|
||||
actions: self.read_slice(code_length)?,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::string::SwfStr;
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Action<'a> {
|
||||
|
@ -157,15 +158,7 @@ pub struct Function<'a> {
|
|||
pub name: &'a SwfStr,
|
||||
pub register_count: u8,
|
||||
pub params: Vec<FunctionParam<'a>>,
|
||||
pub preload_parent: bool,
|
||||
pub preload_root: bool,
|
||||
pub suppress_super: bool,
|
||||
pub preload_super: bool,
|
||||
pub suppress_arguments: bool,
|
||||
pub preload_arguments: bool,
|
||||
pub suppress_this: bool,
|
||||
pub preload_this: bool,
|
||||
pub preload_global: bool,
|
||||
pub flags: FunctionFlags,
|
||||
pub actions: &'a [u8],
|
||||
}
|
||||
|
||||
|
@ -175,6 +168,20 @@ pub struct FunctionParam<'a> {
|
|||
pub register_index: Option<u8>,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct FunctionFlags: u16 {
|
||||
const PRELOAD_THIS = 1 << 0;
|
||||
const SUPPRESS_THIS = 1 << 1;
|
||||
const PRELOAD_ARGUMENTS = 1 << 2;
|
||||
const SUPPRESS_ARGUMENTS = 1 << 3;
|
||||
const PRELOAD_SUPER = 1 << 4;
|
||||
const SUPPRESS_SUPER = 1 << 5;
|
||||
const PRELOAD_ROOT = 1 << 6;
|
||||
const PRELOAD_PARENT = 1 << 7;
|
||||
const PRELOAD_GLOBAL = 1 << 8;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct TryBlock<'a> {
|
||||
pub try_actions: &'a [u8],
|
||||
|
|
|
@ -144,26 +144,7 @@ impl<W: Write> Writer<W> {
|
|||
self.write_string(function.name)?;
|
||||
self.write_u16(function.params.len() as u16)?;
|
||||
self.write_u8(function.register_count)?;
|
||||
let flags = if function.preload_global {
|
||||
0b1_00000000
|
||||
} else {
|
||||
0
|
||||
} | if function.preload_parent {
|
||||
0b10000000
|
||||
} else {
|
||||
0
|
||||
} | if function.preload_root { 0b1000000 } else { 0 }
|
||||
| if function.suppress_super { 0b100000 } else { 0 }
|
||||
| if function.preload_super { 0b10000 } else { 0 }
|
||||
| if function.suppress_arguments {
|
||||
0b1000
|
||||
} else {
|
||||
0
|
||||
}
|
||||
| if function.preload_arguments { 0b100 } else { 0 }
|
||||
| if function.suppress_this { 0b10 } else { 0 }
|
||||
| if function.preload_this { 0b1 } else { 0 };
|
||||
self.write_u16(flags)?;
|
||||
self.write_u16(function.flags.bits())?;
|
||||
for param in &function.params {
|
||||
self.write_u8(if let Some(n) = param.register_index {
|
||||
n
|
||||
|
|
Loading…
Reference in New Issue